[cfe-commits] r65649 - in /cfe/trunk: lib/Sema/CMakeLists.txt lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiation-default-1.cpp
Douglas Gregor
dgregor at apple.com
Fri Feb 27 11:31:53 PST 2009
Author: dgregor
Date: Fri Feb 27 13:31:52 2009
New Revision: 65649
URL: http://llvm.org/viewvc/llvm-project?rev=65649&view=rev
Log:
Implement the basic approach for instantiating types, with a lot of FIXME'd
stubs for those types we don't yet know how to instantiate (everything
that isn't a template parameter!).
We now instantiate default arguments for template type parameters when
needed. This will be our testbed while I fill out the remaining
type-instantiation logic.
Added:
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
Modified:
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=65649&r1=65648&r2=65649&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Fri Feb 27 13:31:52 2009
@@ -21,5 +21,6 @@
SemaOverload.cpp
SemaStmt.cpp
SemaTemplate.cpp
+ SemaTemplateInstantiate.cpp
SemaType.cpp
)
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=65649&r1=65648&r2=65649&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Feb 27 13:31:52 2009
@@ -1579,6 +1579,13 @@
bool CheckTemplateDeclScope(Scope *S,
MultiTemplateParamsArg &TemplateParameterLists);
+ //===--------------------------------------------------------------------===//
+ // C++ Template Instantiation
+ //
+ QualType InstantiateType(QualType T, const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
// Objective-C declarations.
virtual DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=65649&r1=65648&r2=65649&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Feb 27 13:31:52 2009
@@ -5,11 +5,11 @@
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
-//+//===----------------------------------------------------------------------===/
+//===----------------------------------------------------------------------===/
//
// This file implements semantic analysis for C++ templates.
-//+//===----------------------------------------------------------------------===/
+//===----------------------------------------------------------------------===/
#include "Sema.h"
#include "clang/AST/ASTContext.h"
@@ -757,6 +757,17 @@
break;
ArgType = TTP->getDefaultArgument();
+
+ // If the argument type is dependent, instantiate it now based
+ // on the previously-computed template arguments.
+ if (ArgType->isDependentType())
+ ArgType = InstantiateType(ArgType, &Converted[0], Converted.size(),
+ TTP->getDefaultArgumentLoc(),
+ TTP->getDeclName());
+
+ if (ArgType.isNull())
+ break;
+
ArgLoc = TTP->getDefaultArgumentLoc();
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
Added: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=65649&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (added)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Feb 27 13:31:52 2009
@@ -0,0 +1,438 @@
+//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file implements C++ template instantiation.
+//
+//===----------------------------------------------------------------------===/
+
+#include "Sema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Basic/LangOptions.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===/
+// Template Instantiation for Types
+//===----------------------------------------------------------------------===/
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ExtQualType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ExtQualType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const BuiltinType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ assert(false && "BuiltinType is never dependent and cannot be instantiated");
+ return QualType(T, CVR);
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const FixedWidthIntType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate FixedWidthIntType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ComplexType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ComplexType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const PointerType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate PointerType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const BlockPointerType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate BlockPointerType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ReferenceType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ReferenceType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const MemberPointerType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate MemberPointerType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ConstantArrayType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ConstantArrayType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const IncompleteArrayType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate IncompleteArrayType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const VariableArrayType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate VariableArrayType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const DependentSizedArrayType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate DependentSizedArrayType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const VectorType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate VectorType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ExtVectorType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ExtVectorType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const FunctionProtoType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate FunctionProtoType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const FunctionNoProtoType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate FunctionNoProtoType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const TypedefType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate TypedefType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const TypeOfExprType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate TypeOfExprType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const TypeOfType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate TypeOfType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const RecordType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate RecordType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const CXXRecordType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate CXXRecordType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const EnumType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate EnumType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const TemplateTypeParmType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ if (T->getDepth() == 0) {
+ // Replace the template type parameter with its corresponding
+ // template argument.
+ assert(T->getIndex() < NumTemplateArgs && "Wrong # of template args");
+ assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
+ "Template argument kind mismatch");
+ QualType Result = TemplateArgs[T->getIndex()].getAsType();
+ if (Result.isNull() || !CVR)
+ return Result;
+
+ // C++ [dcl.ref]p1:
+ // [...] Cv-qualified references are ill-formed except when
+ // the cv-qualifiers are introduced through the use of a
+ // typedef (7.1.3) or of a template type argument (14.3), in
+ // which case the cv-qualifiers are ignored.
+ if (CVR && Result->isReferenceType())
+ CVR = 0;
+
+ return QualType(Result.getTypePtr(), CVR | Result.getCVRQualifiers());
+ }
+
+ // The template type parameter comes from an inner template (e.g.,
+ // the template parameter list of a member template inside the
+ // template we are instantiating). Create a new template type
+ // parameter with the template "level" reduced by one.
+ return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
+ T->getIndex(),
+ T->getName());
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ClassTemplateSpecializationType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ClassTemplateSpecializationType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ObjCInterfaceType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ObjCInterfaceType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ObjCQualifiedInterfaceType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ObjCQualifiedInterfaceType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ObjCQualifiedIdType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ObjCQualifiedIdType yet");
+ return QualType();
+}
+
+static QualType PerformTypeInstantiation(Sema &SemaRef,
+ const ObjCQualifiedClassType *T,
+ unsigned CVR,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ // FIXME: Implement this
+ assert(false && "Cannot instantiate ObjCQualifiedClassType yet");
+ return QualType();
+}
+
+
+/// \brief Instantiate the type T with a given set of template arguments.
+///
+/// This routine substitutes the given template arguments into the
+/// type T and produces the instantiated type.
+///
+/// \param T the type into which the template arguments will be
+/// substituted. If this type is not dependent, it will be returned
+/// immediately.
+///
+/// \param TemplateArgs the template arguments that will be
+/// substituted for the top-level template parameters within T.
+///
+/// \param NumTemplateArgs the number of template arguments provided
+/// by TemplateArgs.
+///
+/// \param Loc the location in the source code where this substitution
+/// is being performed. It will typically be the location of the
+/// declarator (if we're instantiating the type of some declaration)
+/// or the location of the type in the source code (if, e.g., we're
+/// instantiating the type of a cast expression).
+///
+/// \param Entity the name of the entity associated with a declaration
+/// being instantiated (if any). May be empty to indicate that there
+/// is no such entity (if, e.g., this is a type that occurs as part of
+/// a cast expression) or that the entity has no name (e.g., an
+/// unnamed function parameter).
+///
+/// \returns If the instantiation succeeds, the instantiated
+/// type. Otherwise, produces diagnostics and returns a NULL type.
+QualType Sema::InstantiateType(QualType T,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation Loc, DeclarationName Entity) {
+ // If T is not a dependent type, there is nothing to do.
+ if (!T->isDependentType())
+ return T;
+
+ switch (T->getTypeClass()) {
+#define TYPE(Class, Base) \
+ case Type::Class: \
+ return PerformTypeInstantiation(*this, \
+ cast<Class##Type>(T.getTypePtr()), \
+ T.getCVRQualifiers(), TemplateArgs, \
+ NumTemplateArgs, Loc, Entity);
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ }
+
+ assert(false && "Not all types hav been decided for template instantiation");
+ return QualType();
+}
Added: cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp?rev=65649&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp Fri Feb 27 13:31:52 2009
@@ -0,0 +1,19 @@
+// RUN: clang -fsyntax-only -verify %s
+
+template<typename T, typename U = const T> struct Def1;
+
+template<> struct Def1<int> {
+ void foo();
+};
+
+template<> struct Def1<const int> { // expected-note{{previous definition is here}}
+ void bar();
+};
+
+void test_Def1(Def1<int, const int> *d1, Def1<const int, const int> *d2) {
+ d1->foo();
+ d2->bar();
+}
+
+template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1'}}
+
More information about the cfe-commits
mailing list