From: Douglas Gregor Date: Fri, 27 Feb 2009 19:31:52 +0000 (+0000) Subject: Implement the basic approach for instantiating types, with a lot of FIXME'd X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=99ebf651f1c3fd11eb648dc8d736c192c753f2cf;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65649 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index ce5d6a5435..23809b9309 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -21,5 +21,6 @@ add_clang_library(clangSema SemaOverload.cpp SemaStmt.cpp SemaTemplate.cpp + SemaTemplateInstantiate.cpp SemaType.cpp ) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 22bfee47fa..7875a8183b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1579,6 +1579,13 @@ public: 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, diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5b2e89e8b0..aabbffa4c3 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, 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(*Param)) { diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp new file mode 100644 index 0000000000..e07892e6c1 --- /dev/null +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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(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(); +} diff --git a/test/SemaTemplate/instantiation-default-1.cpp b/test/SemaTemplate/instantiation-default-1.cpp new file mode 100644 index 0000000000..cc616ac770 --- /dev/null +++ b/test/SemaTemplate/instantiation-default-1.cpp @@ -0,0 +1,19 @@ +// RUN: clang -fsyntax-only -verify %s + +template struct Def1; + +template<> struct Def1 { + void foo(); +}; + +template<> struct Def1 { // expected-note{{previous definition is here}} + void bar(); +}; + +void test_Def1(Def1 *d1, Def1 *d2) { + d1->foo(); + d2->bar(); +} + +template<> struct Def1 { }; // expected-error{{redefinition of 'Def1'}} +