//===------- 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" #include "llvm/Support/Compiler.h" using namespace clang; //===----------------------------------------------------------------------===/ // Template Instantiation for Types //===----------------------------------------------------------------------===/ namespace { class VISIBILITY_HIDDEN TemplateTypeInstantiator { Sema &SemaRef; const TemplateArgument *TemplateArgs; unsigned NumTemplateArgs; SourceLocation Loc; DeclarationName Entity; public: TemplateTypeInstantiator(Sema &SemaRef, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation Loc, DeclarationName Entity) : SemaRef(SemaRef), TemplateArgs(TemplateArgs), NumTemplateArgs(NumTemplateArgs), Loc(Loc), Entity(Entity) { } QualType operator()(QualType T) const { return Instantiate(T); } QualType Instantiate(QualType T) const; // Declare instantiate functions for each type. #define TYPE(Class, Base) \ QualType Instantiate##Class##Type(const Class##Type *T, \ unsigned Quals) const; #define ABSTRACT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" }; } QualType TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate ExtQualType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T, unsigned Quals) const { assert(false && "Builtin types are not dependent and cannot be instantiated"); return QualType(T, Quals); } QualType TemplateTypeInstantiator:: InstantiateFixedWidthIntType(const FixedWidthIntType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate FixedWidthIntType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate ComplexType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T, unsigned Quals) const { QualType PointeeType = Instantiate(T->getPointeeType()); if (PointeeType.isNull()) return QualType(); return SemaRef.BuildPointerType(PointeeType, Quals, Loc, Entity); } QualType TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate BlockPointerType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateReferenceType(const ReferenceType *T, unsigned Quals) const { QualType ReferentType = Instantiate(T->getPointeeType()); if (ReferentType.isNull()) return QualType(); return SemaRef.BuildReferenceType(ReferentType, Quals, Loc, Entity); } QualType TemplateTypeInstantiator:: InstantiateMemberPointerType(const MemberPointerType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate MemberPointerType yet"); return QualType(); } QualType TemplateTypeInstantiator:: InstantiateConstantArrayType(const ConstantArrayType *T, unsigned Quals) const { QualType ElementType = Instantiate(T->getElementType()); if (ElementType.isNull()) return ElementType; // Build a temporary integer literal to specify the size for // BuildArrayType. Since we have already checked the size as part of // creating the dependent array type in the first place, we know // there aren't any errors. // FIXME: Is IntTy big enough? Maybe not, but LongLongTy causes // problems that I have yet to investigate. IntegerLiteral ArraySize(T->getSize(), SemaRef.Context.IntTy, Loc); return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), &ArraySize, T->getIndexTypeQualifier(), Loc, Entity); } QualType TemplateTypeInstantiator:: InstantiateIncompleteArrayType(const IncompleteArrayType *T, unsigned Quals) const { QualType ElementType = Instantiate(T->getElementType()); if (ElementType.isNull()) return ElementType; return SemaRef.BuildArrayType(ElementType, T->getSizeModifier(), 0, T->getIndexTypeQualifier(), Loc, Entity); } QualType TemplateTypeInstantiator:: InstantiateVariableArrayType(const VariableArrayType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate VariableArrayType yet"); return QualType(); } QualType TemplateTypeInstantiator:: InstantiateDependentSizedArrayType(const DependentSizedArrayType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate DependentSizedArrayType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate VectorType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateExtVectorType(const ExtVectorType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate ExtVectorType yet"); return QualType(); } QualType TemplateTypeInstantiator:: InstantiateFunctionProtoType(const FunctionProtoType *T, unsigned Quals) const { QualType ResultType = Instantiate(T->getResultType()); if (ResultType.isNull()) return ResultType; llvm::SmallVector ParamTypes; for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(), ParamEnd = T->arg_type_end(); Param != ParamEnd; ++Param) { QualType P = Instantiate(*Param); if (P.isNull()) return P; ParamTypes.push_back(P); } return SemaRef.BuildFunctionType(ResultType, &ParamTypes[0], ParamTypes.size(), T->isVariadic(), T->getTypeQuals(), Loc, Entity); } QualType TemplateTypeInstantiator:: InstantiateFunctionNoProtoType(const FunctionNoProtoType *T, unsigned Quals) const { assert(false && "Functions without prototypes cannot be dependent."); return QualType(); } QualType TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate TypedefType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate TypeOfExprType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate TypeOfType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate RecordType yet"); return QualType(); } QualType TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate EnumType yet"); return QualType(); } QualType TemplateTypeInstantiator:: InstantiateTemplateTypeParmType(const TemplateTypeParmType *T, unsigned Quals) const { 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() || !Quals) 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 (Quals && Result->isReferenceType()) Quals = 0; return QualType(Result.getTypePtr(), Quals | 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()) .getQualifiedType(Quals); } QualType TemplateTypeInstantiator:: InstantiateClassTemplateSpecializationType( const ClassTemplateSpecializationType *T, unsigned Quals) const { // FIXME: Implement this assert(false && "Cannot instantiate ClassTemplateSpecializationType yet"); return QualType(); } QualType TemplateTypeInstantiator:: InstantiateObjCInterfaceType(const ObjCInterfaceType *T, unsigned Quals) const { assert(false && "Objective-C types cannot be dependent"); return QualType(); } QualType TemplateTypeInstantiator:: InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T, unsigned Quals) const { assert(false && "Objective-C types cannot be dependent"); return QualType(); } QualType TemplateTypeInstantiator:: InstantiateObjCQualifiedIdType(const ObjCQualifiedIdType *T, unsigned Quals) const { assert(false && "Objective-C types cannot be dependent"); return QualType(); } QualType TemplateTypeInstantiator:: InstantiateObjCQualifiedClassType(const ObjCQualifiedClassType *T, unsigned Quals) const { assert(false && "Objective-C types cannot be dependent"); return QualType(); } /// \brief The actual implementation of Sema::InstantiateType(). QualType TemplateTypeInstantiator::Instantiate(QualType T) const { // 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 Instantiate##Class##Type(cast(T.getTypePtr()), \ T.getCVRQualifiers()); #define ABSTRACT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" } assert(false && "Not all types have been decoded for instantiation"); 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; TemplateTypeInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs, Loc, Entity); return Instantiator(T); }