| //===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl 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 for declarations. |
| // |
| //===----------------------------------------------------------------------===/ |
| #include "Sema.h" |
| #include "Lookup.h" |
| #include "clang/AST/ASTConsumer.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/DeclTemplate.h" |
| #include "clang/AST/DeclVisitor.h" |
| #include "clang/AST/DependentDiagnostic.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/TypeLoc.h" |
| #include "clang/Basic/PrettyStackTrace.h" |
| #include "clang/Lex/Preprocessor.h" |
| |
| using namespace clang; |
| |
| namespace { |
| class TemplateDeclInstantiator |
| : public DeclVisitor<TemplateDeclInstantiator, Decl *> { |
| Sema &SemaRef; |
| DeclContext *Owner; |
| const MultiLevelTemplateArgumentList &TemplateArgs; |
| |
| void InstantiateAttrs(Decl *Tmpl, Decl *New); |
| |
| public: |
| typedef Sema::OwningExprResult OwningExprResult; |
| |
| TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, |
| const MultiLevelTemplateArgumentList &TemplateArgs) |
| : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { } |
| |
| // FIXME: Once we get closer to completion, replace these manually-written |
| // declarations with automatically-generated ones from |
| // clang/AST/DeclNodes.def. |
| Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); |
| Decl *VisitNamespaceDecl(NamespaceDecl *D); |
| Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); |
| Decl *VisitTypedefDecl(TypedefDecl *D); |
| Decl *VisitVarDecl(VarDecl *D); |
| Decl *VisitFieldDecl(FieldDecl *D); |
| Decl *VisitStaticAssertDecl(StaticAssertDecl *D); |
| Decl *VisitEnumDecl(EnumDecl *D); |
| Decl *VisitEnumConstantDecl(EnumConstantDecl *D); |
| Decl *VisitFriendDecl(FriendDecl *D); |
| Decl *VisitFunctionDecl(FunctionDecl *D, |
| TemplateParameterList *TemplateParams = 0); |
| Decl *VisitCXXRecordDecl(CXXRecordDecl *D); |
| Decl *VisitCXXMethodDecl(CXXMethodDecl *D, |
| TemplateParameterList *TemplateParams = 0); |
| Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D); |
| Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D); |
| Decl *VisitCXXConversionDecl(CXXConversionDecl *D); |
| ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D); |
| Decl *VisitClassTemplateDecl(ClassTemplateDecl *D); |
| Decl *VisitClassTemplatePartialSpecializationDecl( |
| ClassTemplatePartialSpecializationDecl *D); |
| Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); |
| Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); |
| Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); |
| Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); |
| Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D); |
| Decl *VisitUsingDecl(UsingDecl *D); |
| Decl *VisitUsingShadowDecl(UsingShadowDecl *D); |
| Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); |
| Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); |
| |
| // Base case. FIXME: Remove once we can instantiate everything. |
| Decl *VisitDecl(Decl *D) { |
| unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID( |
| Diagnostic::Error, |
| "cannot instantiate %0 yet"); |
| SemaRef.Diag(D->getLocation(), DiagID) |
| << D->getDeclKindName(); |
| |
| return 0; |
| } |
| |
| const LangOptions &getLangOptions() { |
| return SemaRef.getLangOptions(); |
| } |
| |
| // Helper functions for instantiating methods. |
| TypeSourceInfo *SubstFunctionType(FunctionDecl *D, |
| llvm::SmallVectorImpl<ParmVarDecl *> &Params); |
| bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl); |
| bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl); |
| |
| TemplateParameterList * |
| SubstTemplateParams(TemplateParameterList *List); |
| |
| bool SubstQualifier(const DeclaratorDecl *OldDecl, |
| DeclaratorDecl *NewDecl); |
| bool SubstQualifier(const TagDecl *OldDecl, |
| TagDecl *NewDecl); |
| |
| bool InstantiateClassTemplatePartialSpecialization( |
| ClassTemplateDecl *ClassTemplate, |
| ClassTemplatePartialSpecializationDecl *PartialSpec); |
| }; |
| } |
| |
| bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, |
| DeclaratorDecl *NewDecl) { |
| NestedNameSpecifier *OldQual = OldDecl->getQualifier(); |
| if (!OldQual) return false; |
| |
| SourceRange QualRange = OldDecl->getQualifierRange(); |
| |
| NestedNameSpecifier *NewQual |
| = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs); |
| if (!NewQual) |
| return true; |
| |
| NewDecl->setQualifierInfo(NewQual, QualRange); |
| return false; |
| } |
| |
| bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, |
| TagDecl *NewDecl) { |
| NestedNameSpecifier *OldQual = OldDecl->getQualifier(); |
| if (!OldQual) return false; |
| |
| SourceRange QualRange = OldDecl->getQualifierRange(); |
| |
| NestedNameSpecifier *NewQual |
| = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs); |
| if (!NewQual) |
| return true; |
| |
| NewDecl->setQualifierInfo(NewQual, QualRange); |
| return false; |
| } |
| |
| // FIXME: Is this too simple? |
| void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) { |
| for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr; |
| TmplAttr = TmplAttr->getNext()) { |
| |
| // FIXME: Is cloning correct for all attributes? |
| Attr *NewAttr = TmplAttr->clone(SemaRef.Context); |
| |
| New->addAttr(NewAttr); |
| } |
| } |
| |
| Decl * |
| TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { |
| assert(false && "Translation units cannot be instantiated"); |
| return D; |
| } |
| |
| Decl * |
| TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) { |
| assert(false && "Namespaces cannot be instantiated"); |
| return D; |
| } |
| |
| Decl * |
| TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { |
| NamespaceAliasDecl *Inst |
| = NamespaceAliasDecl::Create(SemaRef.Context, Owner, |
| D->getNamespaceLoc(), |
| D->getAliasLoc(), |
| D->getNamespace()->getIdentifier(), |
| D->getQualifierRange(), |
| D->getQualifier(), |
| D->getTargetNameLoc(), |
| D->getNamespace()); |
| Owner->addDecl(Inst); |
| return Inst; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { |
| bool Invalid = false; |
| TypeSourceInfo *DI = D->getTypeSourceInfo(); |
| if (DI->getType()->isDependentType()) { |
| DI = SemaRef.SubstType(DI, TemplateArgs, |
| D->getLocation(), D->getDeclName()); |
| if (!DI) { |
| Invalid = true; |
| DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy); |
| } |
| } |
| |
| // Create the new typedef |
| TypedefDecl *Typedef |
| = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(), |
| D->getIdentifier(), DI); |
| if (Invalid) |
| Typedef->setInvalidDecl(); |
| |
| if (TypedefDecl *Prev = D->getPreviousDeclaration()) { |
| NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, |
| TemplateArgs); |
| Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev)); |
| } |
| |
| Typedef->setAccess(D->getAccess()); |
| Owner->addDecl(Typedef); |
| |
| return Typedef; |
| } |
| |
| /// \brief Instantiate the arguments provided as part of initialization. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| static bool InstantiateInitializationArguments(Sema &SemaRef, |
| Expr **Args, unsigned NumArgs, |
| const MultiLevelTemplateArgumentList &TemplateArgs, |
| llvm::SmallVectorImpl<SourceLocation> &FakeCommaLocs, |
| ASTOwningVector<&ActionBase::DeleteExpr> &InitArgs) { |
| for (unsigned I = 0; I != NumArgs; ++I) { |
| // When we hit the first defaulted argument, break out of the loop: |
| // we don't pass those default arguments on. |
| if (Args[I]->isDefaultArgument()) |
| break; |
| |
| Sema::OwningExprResult Arg = SemaRef.SubstExpr(Args[I], TemplateArgs); |
| if (Arg.isInvalid()) |
| return true; |
| |
| Expr *ArgExpr = (Expr *)Arg.get(); |
| InitArgs.push_back(Arg.release()); |
| |
| // FIXME: We're faking all of the comma locations. Do we need them? |
| FakeCommaLocs.push_back( |
| SemaRef.PP.getLocForEndOfToken(ArgExpr->getLocEnd())); |
| } |
| |
| return false; |
| } |
| |
| /// \brief Instantiate an initializer, breaking it into separate |
| /// initialization arguments. |
| /// |
| /// \param S The semantic analysis object. |
| /// |
| /// \param Init The initializer to instantiate. |
| /// |
| /// \param TemplateArgs Template arguments to be substituted into the |
| /// initializer. |
| /// |
| /// \param NewArgs Will be filled in with the instantiation arguments. |
| /// |
| /// \returns true if an error occurred, false otherwise |
| static bool InstantiateInitializer(Sema &S, Expr *Init, |
| const MultiLevelTemplateArgumentList &TemplateArgs, |
| SourceLocation &LParenLoc, |
| llvm::SmallVector<SourceLocation, 4> &CommaLocs, |
| ASTOwningVector<&ActionBase::DeleteExpr> &NewArgs, |
| SourceLocation &RParenLoc) { |
| NewArgs.clear(); |
| LParenLoc = SourceLocation(); |
| RParenLoc = SourceLocation(); |
| |
| if (!Init) |
| return false; |
| |
| if (CXXExprWithTemporaries *ExprTemp = dyn_cast<CXXExprWithTemporaries>(Init)) |
| Init = ExprTemp->getSubExpr(); |
| |
| while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) |
| Init = Binder->getSubExpr(); |
| |
| if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) |
| Init = ICE->getSubExprAsWritten(); |
| |
| if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { |
| LParenLoc = ParenList->getLParenLoc(); |
| RParenLoc = ParenList->getRParenLoc(); |
| return InstantiateInitializationArguments(S, ParenList->getExprs(), |
| ParenList->getNumExprs(), |
| TemplateArgs, CommaLocs, |
| NewArgs); |
| } |
| |
| if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { |
| if (!isa<CXXTemporaryObjectExpr>(Construct)) { |
| if (InstantiateInitializationArguments(S, |
| Construct->getArgs(), |
| Construct->getNumArgs(), |
| TemplateArgs, |
| CommaLocs, NewArgs)) |
| return true; |
| |
| // FIXME: Fake locations! |
| LParenLoc = S.PP.getLocForEndOfToken(Init->getLocStart()); |
| RParenLoc = CommaLocs.empty()? LParenLoc : CommaLocs.back(); |
| return false; |
| } |
| } |
| |
| Sema::OwningExprResult Result = S.SubstExpr(Init, TemplateArgs); |
| if (Result.isInvalid()) |
| return true; |
| |
| NewArgs.push_back(Result.takeAs<Expr>()); |
| return false; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { |
| // Do substitution on the type of the declaration |
| TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), |
| TemplateArgs, |
| D->getTypeSpecStartLoc(), |
| D->getDeclName()); |
| if (!DI) |
| return 0; |
| |
| // Build the instantiated declaration |
| VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner, |
| D->getLocation(), D->getIdentifier(), |
| DI->getType(), DI, |
| D->getStorageClass()); |
| Var->setThreadSpecified(D->isThreadSpecified()); |
| Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); |
| Var->setDeclaredInCondition(D->isDeclaredInCondition()); |
| |
| // Substitute the nested name specifier, if any. |
| if (SubstQualifier(D, Var)) |
| return 0; |
| |
| // If we are instantiating a static data member defined |
| // out-of-line, the instantiation will have the same lexical |
| // context (which will be a namespace scope) as the template. |
| if (D->isOutOfLine()) |
| Var->setLexicalDeclContext(D->getLexicalDeclContext()); |
| |
| Var->setAccess(D->getAccess()); |
| |
| // FIXME: In theory, we could have a previous declaration for variables that |
| // are not static data members. |
| bool Redeclaration = false; |
| // FIXME: having to fake up a LookupResult is dumb. |
| LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(), |
| Sema::LookupOrdinaryName, Sema::ForRedeclaration); |
| if (D->isStaticDataMember()) |
| SemaRef.LookupQualifiedName(Previous, Owner, false); |
| SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration); |
| |
| if (D->isOutOfLine()) { |
| D->getLexicalDeclContext()->addDecl(Var); |
| Owner->makeDeclVisibleInContext(Var); |
| } else { |
| Owner->addDecl(Var); |
| } |
| |
| // Link instantiations of static data members back to the template from |
| // which they were instantiated. |
| if (Var->isStaticDataMember()) |
| SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, |
| TSK_ImplicitInstantiation); |
| |
| if (Var->getAnyInitializer()) { |
| // We already have an initializer in the class. |
| } else if (D->getInit()) { |
| if (Var->isStaticDataMember() && !D->isOutOfLine()) |
| SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated); |
| else |
| SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); |
| |
| // Instantiate the initializer. |
| SourceLocation LParenLoc, RParenLoc; |
| llvm::SmallVector<SourceLocation, 4> CommaLocs; |
| ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef); |
| if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc, |
| CommaLocs, InitArgs, RParenLoc)) { |
| // Attach the initializer to the declaration. |
| if (D->hasCXXDirectInitializer()) { |
| // Add the direct initializer to the declaration. |
| SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var), |
| LParenLoc, |
| move_arg(InitArgs), |
| CommaLocs.data(), |
| RParenLoc); |
| } else if (InitArgs.size() == 1) { |
| Expr *Init = (Expr*)(InitArgs.take()[0]); |
| SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), |
| SemaRef.Owned(Init), |
| false); |
| } else { |
| assert(InitArgs.size() == 0); |
| SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false); |
| } |
| } else { |
| // FIXME: Not too happy about invalidating the declaration |
| // because of a bogus initializer. |
| Var->setInvalidDecl(); |
| } |
| |
| SemaRef.PopExpressionEvaluationContext(); |
| } else if (!Var->isStaticDataMember() || Var->isOutOfLine()) |
| SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false); |
| |
| return Var; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { |
| bool Invalid = false; |
| TypeSourceInfo *DI = D->getTypeSourceInfo(); |
| if (DI->getType()->isDependentType()) { |
| DI = SemaRef.SubstType(DI, TemplateArgs, |
| D->getLocation(), D->getDeclName()); |
| if (!DI) { |
| DI = D->getTypeSourceInfo(); |
| Invalid = true; |
| } else if (DI->getType()->isFunctionType()) { |
| // C++ [temp.arg.type]p3: |
| // If a declaration acquires a function type through a type |
| // dependent on a template-parameter and this causes a |
| // declaration that does not use the syntactic form of a |
| // function declarator to have function type, the program is |
| // ill-formed. |
| SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function) |
| << DI->getType(); |
| Invalid = true; |
| } |
| } |
| |
| Expr *BitWidth = D->getBitWidth(); |
| if (Invalid) |
| BitWidth = 0; |
| else if (BitWidth) { |
| // The bit-width expression is not potentially evaluated. |
| EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); |
| |
| OwningExprResult InstantiatedBitWidth |
| = SemaRef.SubstExpr(BitWidth, TemplateArgs); |
| if (InstantiatedBitWidth.isInvalid()) { |
| Invalid = true; |
| BitWidth = 0; |
| } else |
| BitWidth = InstantiatedBitWidth.takeAs<Expr>(); |
| } |
| |
| FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), |
| DI->getType(), DI, |
| cast<RecordDecl>(Owner), |
| D->getLocation(), |
| D->isMutable(), |
| BitWidth, |
| D->getTypeSpecStartLoc(), |
| D->getAccess(), |
| 0); |
| if (!Field) { |
| cast<Decl>(Owner)->setInvalidDecl(); |
| return 0; |
| } |
| |
| InstantiateAttrs(D, Field); |
| |
| if (Invalid) |
| Field->setInvalidDecl(); |
| |
| if (!Field->getDeclName()) { |
| // Keep track of where this decl came from. |
| SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D); |
| } |
| |
| Field->setImplicit(D->isImplicit()); |
| Field->setAccess(D->getAccess()); |
| Owner->addDecl(Field); |
| |
| return Field; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { |
| FriendDecl::FriendUnion FU; |
| |
| // Handle friend type expressions by simply substituting template |
| // parameters into the pattern type. |
| if (TypeSourceInfo *Ty = D->getFriendType()) { |
| TypeSourceInfo *InstTy = |
| SemaRef.SubstType(Ty, TemplateArgs, |
| D->getLocation(), DeclarationName()); |
| if (!InstTy) return 0; |
| |
| // This assertion is valid because the source type was necessarily |
| // an elaborated-type-specifier with a record tag. |
| assert(getLangOptions().CPlusPlus0x || InstTy->getType()->isRecordType()); |
| |
| FU = InstTy; |
| |
| // Handle everything else by appropriate substitution. |
| } else { |
| NamedDecl *ND = D->getFriendDecl(); |
| assert(ND && "friend decl must be a decl or a type!"); |
| |
| // FIXME: We have a problem here, because the nested call to Visit(ND) |
| // will inject the thing that the friend references into the current |
| // owner, which is wrong. |
| Decl *NewND; |
| |
| // Hack to make this work almost well pending a rewrite. |
| if (ND->getDeclContext()->isRecord()) { |
| // FIXME: Hack to avoid crashing when incorrectly trying to instantiate |
| // templated friend declarations. This doesn't produce a correct AST; |
| // however this is sufficient for some AST analysis. The real solution |
| // must be put in place during the pending rewrite. See PR5848. |
| return 0; |
| } else if (D->wasSpecialization()) { |
| // Totally egregious hack to work around PR5866 |
| return 0; |
| } else { |
| NewND = Visit(ND); |
| } |
| if (!NewND) return 0; |
| |
| FU = cast<NamedDecl>(NewND); |
| } |
| |
| FriendDecl *FD = |
| FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), FU, |
| D->getFriendLoc()); |
| FD->setAccess(AS_public); |
| Owner->addDecl(FD); |
| return FD; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { |
| Expr *AssertExpr = D->getAssertExpr(); |
| |
| // The expression in a static assertion is not potentially evaluated. |
| EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); |
| |
| OwningExprResult InstantiatedAssertExpr |
| = SemaRef.SubstExpr(AssertExpr, TemplateArgs); |
| if (InstantiatedAssertExpr.isInvalid()) |
| return 0; |
| |
| OwningExprResult Message(SemaRef, D->getMessage()); |
| D->getMessage()->Retain(); |
| Decl *StaticAssert |
| = SemaRef.ActOnStaticAssertDeclaration(D->getLocation(), |
| move(InstantiatedAssertExpr), |
| move(Message)).getAs<Decl>(); |
| return StaticAssert; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { |
| EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, |
| D->getLocation(), D->getIdentifier(), |
| D->getTagKeywordLoc(), |
| /*PrevDecl=*/0); |
| Enum->setInstantiationOfMemberEnum(D); |
| Enum->setAccess(D->getAccess()); |
| if (SubstQualifier(D, Enum)) return 0; |
| Owner->addDecl(Enum); |
| Enum->startDefinition(); |
| |
| if (D->getDeclContext()->isFunctionOrMethod()) |
| SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); |
| |
| llvm::SmallVector<Sema::DeclPtrTy, 4> Enumerators; |
| |
| EnumConstantDecl *LastEnumConst = 0; |
| for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(), |
| ECEnd = D->enumerator_end(); |
| EC != ECEnd; ++EC) { |
| // The specified value for the enumerator. |
| OwningExprResult Value = SemaRef.Owned((Expr *)0); |
| if (Expr *UninstValue = EC->getInitExpr()) { |
| // The enumerator's value expression is not potentially evaluated. |
| EnterExpressionEvaluationContext Unevaluated(SemaRef, |
| Action::Unevaluated); |
| |
| Value = SemaRef.SubstExpr(UninstValue, TemplateArgs); |
| } |
| |
| // Drop the initial value and continue. |
| bool isInvalid = false; |
| if (Value.isInvalid()) { |
| Value = SemaRef.Owned((Expr *)0); |
| isInvalid = true; |
| } |
| |
| EnumConstantDecl *EnumConst |
| = SemaRef.CheckEnumConstant(Enum, LastEnumConst, |
| EC->getLocation(), EC->getIdentifier(), |
| move(Value)); |
| |
| if (isInvalid) { |
| if (EnumConst) |
| EnumConst->setInvalidDecl(); |
| Enum->setInvalidDecl(); |
| } |
| |
| if (EnumConst) { |
| EnumConst->setAccess(Enum->getAccess()); |
| Enum->addDecl(EnumConst); |
| Enumerators.push_back(Sema::DeclPtrTy::make(EnumConst)); |
| LastEnumConst = EnumConst; |
| |
| if (D->getDeclContext()->isFunctionOrMethod()) { |
| // If the enumeration is within a function or method, record the enum |
| // constant as a local. |
| SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst); |
| } |
| } |
| } |
| |
| // FIXME: Fixup LBraceLoc and RBraceLoc |
| // FIXME: Empty Scope and AttributeList (required to handle attribute packed). |
| SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), SourceLocation(), |
| Sema::DeclPtrTy::make(Enum), |
| &Enumerators[0], Enumerators.size(), |
| 0, 0); |
| |
| return Enum; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { |
| assert(false && "EnumConstantDecls can only occur within EnumDecls."); |
| return 0; |
| } |
| |
| namespace { |
| class SortDeclByLocation { |
| SourceManager &SourceMgr; |
| |
| public: |
| explicit SortDeclByLocation(SourceManager &SourceMgr) |
| : SourceMgr(SourceMgr) { } |
| |
| bool operator()(const Decl *X, const Decl *Y) const { |
| return SourceMgr.isBeforeInTranslationUnit(X->getLocation(), |
| Y->getLocation()); |
| } |
| }; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { |
| bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None); |
| |
| // Create a local instantiation scope for this class template, which |
| // will contain the instantiations of the template parameters. |
| Sema::LocalInstantiationScope Scope(SemaRef); |
| TemplateParameterList *TempParams = D->getTemplateParameters(); |
| TemplateParameterList *InstParams = SubstTemplateParams(TempParams); |
| if (!InstParams) |
| return NULL; |
| |
| CXXRecordDecl *Pattern = D->getTemplatedDecl(); |
| |
| // Instantiate the qualifier. We have to do this first in case |
| // we're a friend declaration, because if we are then we need to put |
| // the new declaration in the appropriate context. |
| NestedNameSpecifier *Qualifier = Pattern->getQualifier(); |
| if (Qualifier) { |
| Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, |
| Pattern->getQualifierRange(), |
| TemplateArgs); |
| if (!Qualifier) return 0; |
| } |
| |
| CXXRecordDecl *PrevDecl = 0; |
| ClassTemplateDecl *PrevClassTemplate = 0; |
| |
| // If this isn't a friend, then it's a member template, in which |
| // case we just want to build the instantiation in the |
| // specialization. If it is a friend, we want to build it in |
| // the appropriate context. |
| DeclContext *DC = Owner; |
| if (isFriend) { |
| if (Qualifier) { |
| CXXScopeSpec SS; |
| SS.setScopeRep(Qualifier); |
| SS.setRange(Pattern->getQualifierRange()); |
| DC = SemaRef.computeDeclContext(SS); |
| if (!DC) return 0; |
| } else { |
| DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(), |
| Pattern->getDeclContext(), |
| TemplateArgs); |
| } |
| |
| // Look for a previous declaration of the template in the owning |
| // context. |
| LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(), |
| Sema::LookupOrdinaryName, Sema::ForRedeclaration); |
| SemaRef.LookupQualifiedName(R, DC); |
| |
| if (R.isSingleResult()) { |
| PrevClassTemplate = R.getAsSingle<ClassTemplateDecl>(); |
| if (PrevClassTemplate) |
| PrevDecl = PrevClassTemplate->getTemplatedDecl(); |
| } |
| |
| if (!PrevClassTemplate && Qualifier) { |
| SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) |
| << Pattern->getDeclName() << Pattern->getQualifierRange(); |
| return 0; |
| } |
| |
| if (PrevClassTemplate) { |
| TemplateParameterList *PrevParams |
| = PrevClassTemplate->getTemplateParameters(); |
| |
| // Make sure the parameter lists match. |
| if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, |
| /*Complain=*/true, |
| Sema::TPL_TemplateMatch)) |
| return 0; |
| |
| // Do some additional validation, then merge default arguments |
| // from the existing declarations. |
| if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams, |
| Sema::TPC_ClassTemplate)) |
| return 0; |
| } |
| } |
| |
| CXXRecordDecl *RecordInst |
| = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC, |
| Pattern->getLocation(), Pattern->getIdentifier(), |
| Pattern->getTagKeywordLoc(), PrevDecl, |
| /*DelayTypeCreation=*/true); |
| |
| if (Qualifier) |
| RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange()); |
| |
| ClassTemplateDecl *Inst |
| = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), |
| D->getIdentifier(), InstParams, RecordInst, |
| PrevClassTemplate); |
| RecordInst->setDescribedClassTemplate(Inst); |
| if (isFriend) { |
| Inst->setObjectOfFriendDecl(PrevClassTemplate != 0); |
| // TODO: do we want to track the instantiation progeny of this |
| // friend target decl? |
| } else { |
| Inst->setAccess(D->getAccess()); |
| Inst->setInstantiatedFromMemberTemplate(D); |
| } |
| |
| // Trigger creation of the type for the instantiation. |
| SemaRef.Context.getInjectedClassNameType(RecordInst, |
| Inst->getInjectedClassNameSpecialization(SemaRef.Context)); |
| |
| // Finish handling of friends. |
| if (isFriend) { |
| DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false); |
| return Inst; |
| } |
| |
| Inst->setAccess(D->getAccess()); |
| Owner->addDecl(Inst); |
| |
| // First, we sort the partial specializations by location, so |
| // that we instantiate them in the order they were declared. |
| llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; |
| for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator |
| P = D->getPartialSpecializations().begin(), |
| PEnd = D->getPartialSpecializations().end(); |
| P != PEnd; ++P) |
| PartialSpecs.push_back(&*P); |
| std::sort(PartialSpecs.begin(), PartialSpecs.end(), |
| SortDeclByLocation(SemaRef.SourceMgr)); |
| |
| // Instantiate all of the partial specializations of this member class |
| // template. |
| for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) |
| InstantiateClassTemplatePartialSpecialization(Inst, PartialSpecs[I]); |
| |
| return Inst; |
| } |
| |
| Decl * |
| TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( |
| ClassTemplatePartialSpecializationDecl *D) { |
| ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate(); |
| |
| // Lookup the already-instantiated declaration in the instantiation |
| // of the class template and return that. |
| DeclContext::lookup_result Found |
| = Owner->lookup(ClassTemplate->getDeclName()); |
| if (Found.first == Found.second) |
| return 0; |
| |
| ClassTemplateDecl *InstClassTemplate |
| = dyn_cast<ClassTemplateDecl>(*Found.first); |
| if (!InstClassTemplate) |
| return 0; |
| |
| Decl *DCanon = D->getCanonicalDecl(); |
| for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator |
| P = InstClassTemplate->getPartialSpecializations().begin(), |
| PEnd = InstClassTemplate->getPartialSpecializations().end(); |
| P != PEnd; ++P) { |
| if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon) |
| return &*P; |
| } |
| |
| return 0; |
| } |
| |
| Decl * |
| TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { |
| // Create a local instantiation scope for this function template, which |
| // will contain the instantiations of the template parameters and then get |
| // merged with the local instantiation scope for the function template |
| // itself. |
| Sema::LocalInstantiationScope Scope(SemaRef); |
| |
| TemplateParameterList *TempParams = D->getTemplateParameters(); |
| TemplateParameterList *InstParams = SubstTemplateParams(TempParams); |
| if (!InstParams) |
| return NULL; |
| |
| FunctionDecl *Instantiated = 0; |
| if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl())) |
| Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod, |
| InstParams)); |
| else |
| Instantiated = cast_or_null<FunctionDecl>(VisitFunctionDecl( |
| D->getTemplatedDecl(), |
| InstParams)); |
| |
| if (!Instantiated) |
| return 0; |
| |
| Instantiated->setAccess(D->getAccess()); |
| |
| // Link the instantiated function template declaration to the function |
| // template from which it was instantiated. |
| FunctionTemplateDecl *InstTemplate |
| = Instantiated->getDescribedFunctionTemplate(); |
| InstTemplate->setAccess(D->getAccess()); |
| assert(InstTemplate && |
| "VisitFunctionDecl/CXXMethodDecl didn't create a template!"); |
| |
| bool isFriend = (InstTemplate->getFriendObjectKind() != Decl::FOK_None); |
| |
| // Link the instantiation back to the pattern *unless* this is a |
| // non-definition friend declaration. |
| if (!InstTemplate->getInstantiatedFromMemberTemplate() && |
| !(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition())) |
| InstTemplate->setInstantiatedFromMemberTemplate(D); |
| |
| // Make declarations visible in the appropriate context. |
| if (!isFriend) |
| Owner->addDecl(InstTemplate); |
| |
| return InstTemplate; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { |
| CXXRecordDecl *PrevDecl = 0; |
| if (D->isInjectedClassName()) |
| PrevDecl = cast<CXXRecordDecl>(Owner); |
| else if (D->getPreviousDeclaration()) { |
| NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), |
| D->getPreviousDeclaration(), |
| TemplateArgs); |
| if (!Prev) return 0; |
| PrevDecl = cast<CXXRecordDecl>(Prev); |
| } |
| |
| CXXRecordDecl *Record |
| = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, |
| D->getLocation(), D->getIdentifier(), |
| D->getTagKeywordLoc(), PrevDecl); |
| |
| // Substitute the nested name specifier, if any. |
| if (SubstQualifier(D, Record)) |
| return 0; |
| |
| Record->setImplicit(D->isImplicit()); |
| // FIXME: Check against AS_none is an ugly hack to work around the issue that |
| // the tag decls introduced by friend class declarations don't have an access |
| // specifier. Remove once this area of the code gets sorted out. |
| if (D->getAccess() != AS_none) |
| Record->setAccess(D->getAccess()); |
| if (!D->isInjectedClassName()) |
| Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); |
| |
| // If the original function was part of a friend declaration, |
| // inherit its namespace state. |
| if (Decl::FriendObjectKind FOK = D->getFriendObjectKind()) |
| Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared); |
| |
| Record->setAnonymousStructOrUnion(D->isAnonymousStructOrUnion()); |
| |
| Owner->addDecl(Record); |
| return Record; |
| } |
| |
| /// Normal class members are of more specific types and therefore |
| /// don't make it here. This function serves two purposes: |
| /// 1) instantiating function templates |
| /// 2) substituting friend declarations |
| /// FIXME: preserve function definitions in case #2 |
| Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, |
| TemplateParameterList *TemplateParams) { |
| // Check whether there is already a function template specialization for |
| // this declaration. |
| FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); |
| |
| bool isFriend; |
| if (FunctionTemplate) |
| isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None); |
| else |
| isFriend = (D->getFriendObjectKind() != Decl::FOK_None); |
| |
| void *InsertPos = 0; |
| if (!isFriend && FunctionTemplate && !TemplateParams) { |
| llvm::FoldingSetNodeID ID; |
| FunctionTemplateSpecializationInfo::Profile(ID, |
| TemplateArgs.getInnermost().getFlatArgumentList(), |
| TemplateArgs.getInnermost().flat_size(), |
| SemaRef.Context); |
| |
| FunctionTemplateSpecializationInfo *Info |
| = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, |
| InsertPos); |
| |
| // If we already have a function template specialization, return it. |
| if (Info) |
| return Info->Function; |
| } |
| |
| bool MergeWithParentScope = (TemplateParams != 0) || |
| !(isa<Decl>(Owner) && |
| cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); |
| Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); |
| |
| llvm::SmallVector<ParmVarDecl *, 4> Params; |
| TypeSourceInfo *TInfo = D->getTypeSourceInfo(); |
| TInfo = SubstFunctionType(D, Params); |
| if (!TInfo) |
| return 0; |
| QualType T = TInfo->getType(); |
| |
| NestedNameSpecifier *Qualifier = D->getQualifier(); |
| if (Qualifier) { |
| Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, |
| D->getQualifierRange(), |
| TemplateArgs); |
| if (!Qualifier) return 0; |
| } |
| |
| // If we're instantiating a local function declaration, put the result |
| // in the owner; otherwise we need to find the instantiated context. |
| DeclContext *DC; |
| if (D->getDeclContext()->isFunctionOrMethod()) |
| DC = Owner; |
| else if (isFriend && Qualifier) { |
| CXXScopeSpec SS; |
| SS.setScopeRep(Qualifier); |
| SS.setRange(D->getQualifierRange()); |
| DC = SemaRef.computeDeclContext(SS); |
| if (!DC) return 0; |
| } else { |
| DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), |
| TemplateArgs); |
| } |
| |
| FunctionDecl *Function = |
| FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), |
| D->getDeclName(), T, TInfo, |
| D->getStorageClass(), |
| D->isInlineSpecified(), D->hasWrittenPrototype()); |
| |
| if (Qualifier) |
| Function->setQualifierInfo(Qualifier, D->getQualifierRange()); |
| |
| DeclContext *LexicalDC = Owner; |
| if (!isFriend && D->isOutOfLine()) { |
| assert(D->getDeclContext()->isFileContext()); |
| LexicalDC = D->getDeclContext(); |
| } |
| |
| Function->setLexicalDeclContext(LexicalDC); |
| |
| // Attach the parameters |
| for (unsigned P = 0; P < Params.size(); ++P) |
| Params[P]->setOwningFunction(Function); |
| Function->setParams(Params.data(), Params.size()); |
| |
| if (TemplateParams) { |
| // Our resulting instantiation is actually a function template, since we |
| // are substituting only the outer template parameters. For example, given |
| // |
| // template<typename T> |
| // struct X { |
| // template<typename U> friend void f(T, U); |
| // }; |
| // |
| // X<int> x; |
| // |
| // We are instantiating the friend function template "f" within X<int>, |
| // which means substituting int for T, but leaving "f" as a friend function |
| // template. |
| // Build the function template itself. |
| FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, DC, |
| Function->getLocation(), |
| Function->getDeclName(), |
| TemplateParams, Function); |
| Function->setDescribedFunctionTemplate(FunctionTemplate); |
| |
| FunctionTemplate->setLexicalDeclContext(LexicalDC); |
| |
| if (isFriend && D->isThisDeclarationADefinition()) { |
| // TODO: should we remember this connection regardless of whether |
| // the friend declaration provided a body? |
| FunctionTemplate->setInstantiatedFromMemberTemplate( |
| D->getDescribedFunctionTemplate()); |
| } |
| } else if (FunctionTemplate) { |
| // Record this function template specialization. |
| Function->setFunctionTemplateSpecialization(FunctionTemplate, |
| &TemplateArgs.getInnermost(), |
| InsertPos); |
| } else if (isFriend && D->isThisDeclarationADefinition()) { |
| // TODO: should we remember this connection regardless of whether |
| // the friend declaration provided a body? |
| Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); |
| } |
| |
| if (InitFunctionInstantiation(Function, D)) |
| Function->setInvalidDecl(); |
| |
| bool Redeclaration = false; |
| bool OverloadableAttrRequired = false; |
| |
| LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(), |
| Sema::LookupOrdinaryName, Sema::ForRedeclaration); |
| |
| if (TemplateParams || !FunctionTemplate) { |
| // Look only into the namespace where the friend would be declared to |
| // find a previous declaration. This is the innermost enclosing namespace, |
| // as described in ActOnFriendFunctionDecl. |
| SemaRef.LookupQualifiedName(Previous, DC); |
| |
| // In C++, the previous declaration we find might be a tag type |
| // (class or enum). In this case, the new declaration will hide the |
| // tag type. Note that this does does not apply if we're declaring a |
| // typedef (C++ [dcl.typedef]p4). |
| if (Previous.isSingleTagDecl()) |
| Previous.clear(); |
| } |
| |
| SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous, |
| false, Redeclaration, |
| /*FIXME:*/OverloadableAttrRequired); |
| |
| // If the original function was part of a friend declaration, |
| // inherit its namespace state and add it to the owner. |
| if (isFriend) { |
| NamedDecl *ToFriendD = 0; |
| NamedDecl *PrevDecl; |
| if (TemplateParams) { |
| ToFriendD = cast<NamedDecl>(FunctionTemplate); |
| PrevDecl = FunctionTemplate->getPreviousDeclaration(); |
| } else { |
| ToFriendD = Function; |
| PrevDecl = Function->getPreviousDeclaration(); |
| } |
| ToFriendD->setObjectOfFriendDecl(PrevDecl != NULL); |
| DC->makeDeclVisibleInContext(ToFriendD, /*Recoverable=*/ false); |
| } |
| |
| return Function; |
| } |
| |
| Decl * |
| TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, |
| TemplateParameterList *TemplateParams) { |
| FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); |
| void *InsertPos = 0; |
| if (FunctionTemplate && !TemplateParams) { |
| // We are creating a function template specialization from a function |
| // template. Check whether there is already a function template |
| // specialization for this particular set of template arguments. |
| llvm::FoldingSetNodeID ID; |
| FunctionTemplateSpecializationInfo::Profile(ID, |
| TemplateArgs.getInnermost().getFlatArgumentList(), |
| TemplateArgs.getInnermost().flat_size(), |
| SemaRef.Context); |
| |
| FunctionTemplateSpecializationInfo *Info |
| = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, |
| InsertPos); |
| |
| // If we already have a function template specialization, return it. |
| if (Info) |
| return Info->Function; |
| } |
| |
| bool MergeWithParentScope = (TemplateParams != 0) || |
| !(isa<Decl>(Owner) && |
| cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); |
| Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); |
| |
| llvm::SmallVector<ParmVarDecl *, 4> Params; |
| TypeSourceInfo *TInfo = D->getTypeSourceInfo(); |
| TInfo = SubstFunctionType(D, Params); |
| if (!TInfo) |
| return 0; |
| QualType T = TInfo->getType(); |
| |
| // Build the instantiated method declaration. |
| CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner); |
| CXXMethodDecl *Method = 0; |
| |
| DeclarationName Name = D->getDeclName(); |
| if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { |
| QualType ClassTy = SemaRef.Context.getTypeDeclType(Record); |
| Name = SemaRef.Context.DeclarationNames.getCXXConstructorName( |
| SemaRef.Context.getCanonicalType(ClassTy)); |
| Method = CXXConstructorDecl::Create(SemaRef.Context, Record, |
| Constructor->getLocation(), |
| Name, T, TInfo, |
| Constructor->isExplicit(), |
| Constructor->isInlineSpecified(), false); |
| } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { |
| QualType ClassTy = SemaRef.Context.getTypeDeclType(Record); |
| Name = SemaRef.Context.DeclarationNames.getCXXDestructorName( |
| SemaRef.Context.getCanonicalType(ClassTy)); |
| Method = CXXDestructorDecl::Create(SemaRef.Context, Record, |
| Destructor->getLocation(), Name, |
| T, Destructor->isInlineSpecified(), false); |
| } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { |
| CanQualType ConvTy |
| = SemaRef.Context.getCanonicalType( |
| T->getAs<FunctionType>()->getResultType()); |
| Name = SemaRef.Context.DeclarationNames.getCXXConversionFunctionName( |
| ConvTy); |
| Method = CXXConversionDecl::Create(SemaRef.Context, Record, |
| Conversion->getLocation(), Name, |
| T, TInfo, |
| Conversion->isInlineSpecified(), |
| Conversion->isExplicit()); |
| } else { |
| Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(), |
| D->getDeclName(), T, TInfo, |
| D->isStatic(), D->isInlineSpecified()); |
| } |
| |
| // Substitute the nested name specifier, if any. |
| if (SubstQualifier(D, Method)) |
| return 0; |
| |
| if (TemplateParams) { |
| // Our resulting instantiation is actually a function template, since we |
| // are substituting only the outer template parameters. For example, given |
| // |
| // template<typename T> |
| // struct X { |
| // template<typename U> void f(T, U); |
| // }; |
| // |
| // X<int> x; |
| // |
| // We are instantiating the member template "f" within X<int>, which means |
| // substituting int for T, but leaving "f" as a member function template. |
| // Build the function template itself. |
| FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record, |
| Method->getLocation(), |
| Method->getDeclName(), |
| TemplateParams, Method); |
| if (D->isOutOfLine()) |
| FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext()); |
| Method->setDescribedFunctionTemplate(FunctionTemplate); |
| } else if (FunctionTemplate) { |
| // Record this function template specialization. |
| Method->setFunctionTemplateSpecialization(FunctionTemplate, |
| &TemplateArgs.getInnermost(), |
| InsertPos); |
| } else { |
| // Record that this is an instantiation of a member function. |
| Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); |
| } |
| |
| // If we are instantiating a member function defined |
| // out-of-line, the instantiation will have the same lexical |
| // context (which will be a namespace scope) as the template. |
| if (D->isOutOfLine()) |
| Method->setLexicalDeclContext(D->getLexicalDeclContext()); |
| |
| // Attach the parameters |
| for (unsigned P = 0; P < Params.size(); ++P) |
| Params[P]->setOwningFunction(Method); |
| Method->setParams(Params.data(), Params.size()); |
| |
| if (InitMethodInstantiation(Method, D)) |
| Method->setInvalidDecl(); |
| |
| LookupResult Previous(SemaRef, Name, SourceLocation(), |
| Sema::LookupOrdinaryName, Sema::ForRedeclaration); |
| |
| if (!FunctionTemplate || TemplateParams) { |
| SemaRef.LookupQualifiedName(Previous, Owner); |
| |
| // In C++, the previous declaration we find might be a tag type |
| // (class or enum). In this case, the new declaration will hide the |
| // tag type. Note that this does does not apply if we're declaring a |
| // typedef (C++ [dcl.typedef]p4). |
| if (Previous.isSingleTagDecl()) |
| Previous.clear(); |
| } |
| |
| bool Redeclaration = false; |
| bool OverloadableAttrRequired = false; |
| SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration, |
| /*FIXME:*/OverloadableAttrRequired); |
| |
| if (D->isPure()) |
| SemaRef.CheckPureMethod(Method, SourceRange()); |
| |
| Method->setAccess(D->getAccess()); |
| |
| if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) && |
| !Method->getFriendObjectKind()) |
| Owner->addDecl(Method); |
| |
| return Method; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) { |
| return VisitCXXMethodDecl(D); |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) { |
| return VisitCXXMethodDecl(D); |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { |
| return VisitCXXMethodDecl(D); |
| } |
| |
| ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { |
| QualType T; |
| TypeSourceInfo *DI = D->getTypeSourceInfo(); |
| if (DI) { |
| DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(), |
| D->getDeclName()); |
| if (DI) T = DI->getType(); |
| } else { |
| T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(), |
| D->getDeclName()); |
| DI = 0; |
| } |
| |
| if (T.isNull()) |
| return 0; |
| |
| T = SemaRef.adjustParameterType(T); |
| |
| // Allocate the parameter |
| ParmVarDecl *Param |
| = ParmVarDecl::Create(SemaRef.Context, |
| SemaRef.Context.getTranslationUnitDecl(), |
| D->getLocation(), |
| D->getIdentifier(), T, DI, D->getStorageClass(), 0); |
| |
| // Mark the default argument as being uninstantiated. |
| if (D->hasUninstantiatedDefaultArg()) |
| Param->setUninstantiatedDefaultArg(D->getUninstantiatedDefaultArg()); |
| else if (Expr *Arg = D->getDefaultArg()) |
| Param->setUninstantiatedDefaultArg(Arg); |
| |
| // Note: we don't try to instantiate function parameters until after |
| // we've instantiated the function's type. Therefore, we don't have |
| // to check for 'void' parameter types here. |
| SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); |
| return Param; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( |
| TemplateTypeParmDecl *D) { |
| // TODO: don't always clone when decls are refcounted. |
| const Type* T = D->getTypeForDecl(); |
| assert(T->isTemplateTypeParmType()); |
| const TemplateTypeParmType *TTPT = T->getAs<TemplateTypeParmType>(); |
| |
| TemplateTypeParmDecl *Inst = |
| TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), |
| TTPT->getDepth() - 1, TTPT->getIndex(), |
| TTPT->getName(), |
| D->wasDeclaredWithTypename(), |
| D->isParameterPack()); |
| |
| if (D->hasDefaultArgument()) |
| Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false); |
| |
| // Introduce this template parameter's instantiation into the instantiation |
| // scope. |
| SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst); |
| |
| return Inst; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( |
| NonTypeTemplateParmDecl *D) { |
| // Substitute into the type of the non-type template parameter. |
| QualType T; |
| TypeSourceInfo *DI = D->getTypeSourceInfo(); |
| if (DI) { |
| DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(), |
| D->getDeclName()); |
| if (DI) T = DI->getType(); |
| } else { |
| T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(), |
| D->getDeclName()); |
| DI = 0; |
| } |
| if (T.isNull()) |
| return 0; |
| |
| // Check that this type is acceptable for a non-type template parameter. |
| bool Invalid = false; |
| T = SemaRef.CheckNonTypeTemplateParameterType(T, D->getLocation()); |
| if (T.isNull()) { |
| T = SemaRef.Context.IntTy; |
| Invalid = true; |
| } |
| |
| NonTypeTemplateParmDecl *Param |
| = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), |
| D->getDepth() - 1, D->getPosition(), |
| D->getIdentifier(), T, DI); |
| if (Invalid) |
| Param->setInvalidDecl(); |
| |
| Param->setDefaultArgument(D->getDefaultArgument()); |
| |
| // Introduce this template parameter's instantiation into the instantiation |
| // scope. |
| SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); |
| return Param; |
| } |
| |
| Decl * |
| TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( |
| TemplateTemplateParmDecl *D) { |
| // Instantiate the template parameter list of the template template parameter. |
| TemplateParameterList *TempParams = D->getTemplateParameters(); |
| TemplateParameterList *InstParams; |
| { |
| // Perform the actual substitution of template parameters within a new, |
| // local instantiation scope. |
| Sema::LocalInstantiationScope Scope(SemaRef); |
| InstParams = SubstTemplateParams(TempParams); |
| if (!InstParams) |
| return NULL; |
| } |
| |
| // Build the template template parameter. |
| TemplateTemplateParmDecl *Param |
| = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), |
| D->getDepth() - 1, D->getPosition(), |
| D->getIdentifier(), InstParams); |
| Param->setDefaultArgument(D->getDefaultArgument()); |
| |
| // Introduce this template parameter's instantiation into the instantiation |
| // scope. |
| SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); |
| |
| return Param; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { |
| // Using directives are never dependent, so they require no explicit |
| |
| UsingDirectiveDecl *Inst |
| = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(), |
| D->getNamespaceKeyLocation(), |
| D->getQualifierRange(), D->getQualifier(), |
| D->getIdentLocation(), |
| D->getNominatedNamespace(), |
| D->getCommonAncestor()); |
| Owner->addDecl(Inst); |
| return Inst; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { |
| // The nested name specifier is non-dependent, so no transformation |
| // is required. |
| |
| // We only need to do redeclaration lookups if we're in a class |
| // scope (in fact, it's not really even possible in non-class |
| // scopes). |
| bool CheckRedeclaration = Owner->isRecord(); |
| |
| LookupResult Prev(SemaRef, D->getDeclName(), D->getLocation(), |
| Sema::LookupUsingDeclName, Sema::ForRedeclaration); |
| |
| UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, |
| D->getLocation(), |
| D->getNestedNameRange(), |
| D->getUsingLocation(), |
| D->getTargetNestedNameDecl(), |
| D->getDeclName(), |
| D->isTypeName()); |
| |
| CXXScopeSpec SS; |
| SS.setScopeRep(D->getTargetNestedNameDecl()); |
| SS.setRange(D->getNestedNameRange()); |
| |
| if (CheckRedeclaration) { |
| Prev.setHideTags(false); |
| SemaRef.LookupQualifiedName(Prev, Owner); |
| |
| // Check for invalid redeclarations. |
| if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(), |
| D->isTypeName(), SS, |
| D->getLocation(), Prev)) |
| NewUD->setInvalidDecl(); |
| |
| } |
| |
| if (!NewUD->isInvalidDecl() && |
| SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS, |
| D->getLocation())) |
| NewUD->setInvalidDecl(); |
| |
| SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D); |
| NewUD->setAccess(D->getAccess()); |
| Owner->addDecl(NewUD); |
| |
| // Don't process the shadow decls for an invalid decl. |
| if (NewUD->isInvalidDecl()) |
| return NewUD; |
| |
| bool isFunctionScope = Owner->isFunctionOrMethod(); |
| |
| // Process the shadow decls. |
| for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end(); |
| I != E; ++I) { |
| UsingShadowDecl *Shadow = *I; |
| NamedDecl *InstTarget = |
| cast<NamedDecl>(SemaRef.FindInstantiatedDecl(Shadow->getLocation(), |
| Shadow->getTargetDecl(), |
| TemplateArgs)); |
| |
| if (CheckRedeclaration && |
| SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev)) |
| continue; |
| |
| UsingShadowDecl *InstShadow |
| = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget); |
| SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); |
| |
| if (isFunctionScope) |
| SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); |
| } |
| |
| return NewUD; |
| } |
| |
| Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) { |
| // Ignore these; we handle them in bulk when processing the UsingDecl. |
| return 0; |
| } |
| |
| Decl * TemplateDeclInstantiator |
| ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { |
| NestedNameSpecifier *NNS = |
| SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), |
| D->getTargetNestedNameRange(), |
| TemplateArgs); |
| if (!NNS) |
| return 0; |
| |
| CXXScopeSpec SS; |
| SS.setRange(D->getTargetNestedNameRange()); |
| SS.setScopeRep(NNS); |
| |
| NamedDecl *UD = |
| SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(), |
| D->getUsingLoc(), SS, D->getLocation(), |
| D->getDeclName(), 0, |
| /*instantiation*/ true, |
| /*typename*/ true, D->getTypenameLoc()); |
| if (UD) |
| SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D); |
| |
| return UD; |
| } |
| |
| Decl * TemplateDeclInstantiator |
| ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { |
| NestedNameSpecifier *NNS = |
| SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), |
| D->getTargetNestedNameRange(), |
| TemplateArgs); |
| if (!NNS) |
| return 0; |
| |
| CXXScopeSpec SS; |
| SS.setRange(D->getTargetNestedNameRange()); |
| SS.setScopeRep(NNS); |
| |
| NamedDecl *UD = |
| SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(), |
| D->getUsingLoc(), SS, D->getLocation(), |
| D->getDeclName(), 0, |
| /*instantiation*/ true, |
| /*typename*/ false, SourceLocation()); |
| if (UD) |
| SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D); |
| |
| return UD; |
| } |
| |
| Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, |
| const MultiLevelTemplateArgumentList &TemplateArgs) { |
| TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); |
| if (D->isInvalidDecl()) |
| return 0; |
| |
| return Instantiator.Visit(D); |
| } |
| |
| /// \brief Instantiates a nested template parameter list in the current |
| /// instantiation context. |
| /// |
| /// \param L The parameter list to instantiate |
| /// |
| /// \returns NULL if there was an error |
| TemplateParameterList * |
| TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { |
| // Get errors for all the parameters before bailing out. |
| bool Invalid = false; |
| |
| unsigned N = L->size(); |
| typedef llvm::SmallVector<NamedDecl *, 8> ParamVector; |
| ParamVector Params; |
| Params.reserve(N); |
| for (TemplateParameterList::iterator PI = L->begin(), PE = L->end(); |
| PI != PE; ++PI) { |
| NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI)); |
| Params.push_back(D); |
| Invalid = Invalid || !D || D->isInvalidDecl(); |
| } |
| |
| // Clean up if we had an error. |
| if (Invalid) { |
| for (ParamVector::iterator PI = Params.begin(), PE = Params.end(); |
| PI != PE; ++PI) |
| if (*PI) |
| (*PI)->Destroy(SemaRef.Context); |
| return NULL; |
| } |
| |
| TemplateParameterList *InstL |
| = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(), |
| L->getLAngleLoc(), &Params.front(), N, |
| L->getRAngleLoc()); |
| return InstL; |
| } |
| |
| /// \brief Instantiate the declaration of a class template partial |
| /// specialization. |
| /// |
| /// \param ClassTemplate the (instantiated) class template that is partially |
| // specialized by the instantiation of \p PartialSpec. |
| /// |
| /// \param PartialSpec the (uninstantiated) class template partial |
| /// specialization that we are instantiating. |
| /// |
| /// \returns true if there was an error, false otherwise. |
| bool |
| TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( |
| ClassTemplateDecl *ClassTemplate, |
| ClassTemplatePartialSpecializationDecl *PartialSpec) { |
| // Create a local instantiation scope for this class template partial |
| // specialization, which will contain the instantiations of the template |
| // parameters. |
| Sema::LocalInstantiationScope Scope(SemaRef); |
| |
| // Substitute into the template parameters of the class template partial |
| // specialization. |
| TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); |
| TemplateParameterList *InstParams = SubstTemplateParams(TempParams); |
| if (!InstParams) |
| return true; |
| |
| // Substitute into the template arguments of the class template partial |
| // specialization. |
| const TemplateArgumentLoc *PartialSpecTemplateArgs |
| = PartialSpec->getTemplateArgsAsWritten(); |
| unsigned N = PartialSpec->getNumTemplateArgsAsWritten(); |
| |
| TemplateArgumentListInfo InstTemplateArgs; // no angle locations |
| for (unsigned I = 0; I != N; ++I) { |
| TemplateArgumentLoc Loc; |
| if (SemaRef.Subst(PartialSpecTemplateArgs[I], Loc, TemplateArgs)) |
| return true; |
| InstTemplateArgs.addArgument(Loc); |
| } |
| |
| |
| // Check that the template argument list is well-formed for this |
| // class template. |
| TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), |
| InstTemplateArgs.size()); |
| if (SemaRef.CheckTemplateArgumentList(ClassTemplate, |
| PartialSpec->getLocation(), |
| InstTemplateArgs, |
| false, |
| Converted)) |
| return true; |
| |
| // Figure out where to insert this class template partial specialization |
| // in the member template's set of class template partial specializations. |
| llvm::FoldingSetNodeID ID; |
| ClassTemplatePartialSpecializationDecl::Profile(ID, |
| Converted.getFlatArguments(), |
| Converted.flatSize(), |
| SemaRef.Context); |
| void *InsertPos = 0; |
| ClassTemplateSpecializationDecl *PrevDecl |
| = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID, |
| InsertPos); |
| |
| // Build the canonical type that describes the converted template |
| // arguments of the class template partial specialization. |
| QualType CanonType |
| = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), |
| Converted.getFlatArguments(), |
| Converted.flatSize()); |
| |
| // Build the fully-sugared type for this class template |
| // specialization as the user wrote in the specialization |
| // itself. This means that we'll pretty-print the type retrieved |
| // from the specialization's declaration the way that the user |
| // actually wrote the specialization, rather than formatting the |
| // name based on the "canonical" representation used to store the |
| // template arguments in the specialization. |
| TypeSourceInfo *WrittenTy |
| = SemaRef.Context.getTemplateSpecializationTypeInfo( |
| TemplateName(ClassTemplate), |
| PartialSpec->getLocation(), |
| InstTemplateArgs, |
| CanonType); |
| |
| if (PrevDecl) { |
| // We've already seen a partial specialization with the same template |
| // parameters and template arguments. This can happen, for example, when |
| // substituting the outer template arguments ends up causing two |
| // class template partial specializations of a member class template |
| // to have identical forms, e.g., |
| // |
| // template<typename T, typename U> |
| // struct Outer { |
| // template<typename X, typename Y> struct Inner; |
| // template<typename Y> struct Inner<T, Y>; |
| // template<typename Y> struct Inner<U, Y>; |
| // }; |
| // |
| // Outer<int, int> outer; // error: the partial specializations of Inner |
| // // have the same signature. |
| SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) |
| << WrittenTy; |
| SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) |
| << SemaRef.Context.getTypeDeclType(PrevDecl); |
| return true; |
| } |
| |
| |
| // Create the class template partial specialization declaration. |
| ClassTemplatePartialSpecializationDecl *InstPartialSpec |
| = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, Owner, |
| PartialSpec->getLocation(), |
| InstParams, |
| ClassTemplate, |
| Converted, |
| InstTemplateArgs, |
| CanonType, |
| 0); |
| // Substitute the nested name specifier, if any. |
| if (SubstQualifier(PartialSpec, InstPartialSpec)) |
| return 0; |
| |
| InstPartialSpec->setInstantiatedFromMember(PartialSpec); |
| InstPartialSpec->setTypeAsWritten(WrittenTy); |
| |
| // Add this partial specialization to the set of class template partial |
| // specializations. |
| ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec, |
| InsertPos); |
| return false; |
| } |
| |
| bool |
| Sema::CheckInstantiatedParams(llvm::SmallVectorImpl<ParmVarDecl*> &Params) { |
| bool Invalid = false; |
| for (unsigned i = 0, i_end = Params.size(); i != i_end; ++i) |
| if (ParmVarDecl *PInst = Params[i]) { |
| if (PInst->isInvalidDecl()) |
| Invalid = true; |
| else if (PInst->getType()->isVoidType()) { |
| Diag(PInst->getLocation(), diag::err_param_with_void_type); |
| PInst->setInvalidDecl(); |
| Invalid = true; |
| } |
| else if (RequireNonAbstractType(PInst->getLocation(), |
| PInst->getType(), |
| diag::err_abstract_type_in_decl, |
| Sema::AbstractParamType)) { |
| PInst->setInvalidDecl(); |
| Invalid = true; |
| } |
| } |
| return Invalid; |
| } |
| |
| TypeSourceInfo* |
| TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, |
| llvm::SmallVectorImpl<ParmVarDecl *> &Params) { |
| TypeSourceInfo *OldTInfo = D->getTypeSourceInfo(); |
| assert(OldTInfo && "substituting function without type source info"); |
| assert(Params.empty() && "parameter vector is non-empty at start"); |
| TypeSourceInfo *NewTInfo = SemaRef.SubstType(OldTInfo, TemplateArgs, |
| D->getTypeSpecStartLoc(), |
| D->getDeclName()); |
| if (!NewTInfo) |
| return 0; |
| |
| // Get parameters from the new type info. |
| TypeLoc NewTL = NewTInfo->getTypeLoc(); |
| FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL); |
| assert(NewProtoLoc && "Missing prototype?"); |
| for (unsigned i = 0, i_end = NewProtoLoc->getNumArgs(); i != i_end; ++i) |
| Params.push_back(NewProtoLoc->getArg(i)); |
| |
| return NewTInfo; |
| } |
| |
| /// \brief Initializes the common fields of an instantiation function |
| /// declaration (New) from the corresponding fields of its template (Tmpl). |
| /// |
| /// \returns true if there was an error |
| bool |
| TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, |
| FunctionDecl *Tmpl) { |
| if (Tmpl->isDeleted()) |
| New->setDeleted(); |
| |
| // If we are performing substituting explicitly-specified template arguments |
| // or deduced template arguments into a function template and we reach this |
| // point, we are now past the point where SFINAE applies and have committed |
| // to keeping the new function template specialization. We therefore |
| // convert the active template instantiation for the function template |
| // into a template instantiation for this specific function template |
| // specialization, which is not a SFINAE context, so that we diagnose any |
| // further errors in the declaration itself. |
| typedef Sema::ActiveTemplateInstantiation ActiveInstType; |
| ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back(); |
| if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || |
| ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { |
| if (FunctionTemplateDecl *FunTmpl |
| = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) { |
| assert(FunTmpl->getTemplatedDecl() == Tmpl && |
| "Deduction from the wrong function template?"); |
| (void) FunTmpl; |
| ActiveInst.Kind = ActiveInstType::TemplateInstantiation; |
| ActiveInst.Entity = reinterpret_cast<uintptr_t>(New); |
| --SemaRef.NonInstantiationEntries; |
| } |
| } |
| |
| const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>(); |
| assert(Proto && "Function template without prototype?"); |
| |
| if (Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec() || |
| Proto->getNoReturnAttr()) { |
| // The function has an exception specification or a "noreturn" |
| // attribute. Substitute into each of the exception types. |
| llvm::SmallVector<QualType, 4> Exceptions; |
| for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) { |
| // FIXME: Poor location information! |
| QualType T |
| = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs, |
| New->getLocation(), New->getDeclName()); |
| if (T.isNull() || |
| SemaRef.CheckSpecifiedExceptionType(T, New->getLocation())) |
| continue; |
| |
| Exceptions.push_back(T); |
| } |
| |
| // Rebuild the function type |
| |
| const FunctionProtoType *NewProto |
| = New->getType()->getAs<FunctionProtoType>(); |
| assert(NewProto && "Template instantiation without function prototype?"); |
| New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), |
| NewProto->arg_type_begin(), |
| NewProto->getNumArgs(), |
| NewProto->isVariadic(), |
| NewProto->getTypeQuals(), |
| Proto->hasExceptionSpec(), |
| Proto->hasAnyExceptionSpec(), |
| Exceptions.size(), |
| Exceptions.data(), |
| Proto->getNoReturnAttr(), |
| Proto->getCallConv())); |
| } |
| |
| return false; |
| } |
| |
| /// \brief Initializes common fields of an instantiated method |
| /// declaration (New) from the corresponding fields of its template |
| /// (Tmpl). |
| /// |
| /// \returns true if there was an error |
| bool |
| TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, |
| CXXMethodDecl *Tmpl) { |
| if (InitFunctionInstantiation(New, Tmpl)) |
| return true; |
| |
| CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner); |
| New->setAccess(Tmpl->getAccess()); |
| if (Tmpl->isVirtualAsWritten()) |
| Record->setMethodAsVirtual(New); |
| |
| // FIXME: attributes |
| // FIXME: New needs a pointer to Tmpl |
| return false; |
| } |
| |
| /// \brief Instantiate the definition of the given function from its |
| /// template. |
| /// |
| /// \param PointOfInstantiation the point at which the instantiation was |
| /// required. Note that this is not precisely a "point of instantiation" |
| /// for the function, but it's close. |
| /// |
| /// \param Function the already-instantiated declaration of a |
| /// function template specialization or member function of a class template |
| /// specialization. |
| /// |
| /// \param Recursive if true, recursively instantiates any functions that |
| /// are required by this instantiation. |
| /// |
| /// \param DefinitionRequired if true, then we are performing an explicit |
| /// instantiation where the body of the function is required. Complain if |
| /// there is no such body. |
| void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, |
| FunctionDecl *Function, |
| bool Recursive, |
| bool DefinitionRequired) { |
| if (Function->isInvalidDecl()) |
| return; |
| |
| assert(!Function->getBody() && "Already instantiated!"); |
| |
| // Never instantiate an explicit specialization. |
| if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) |
| return; |
| |
| // Find the function body that we'll be substituting. |
| const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern(); |
| Stmt *Pattern = 0; |
| if (PatternDecl) |
| Pattern = PatternDecl->getBody(PatternDecl); |
| |
| if (!Pattern) { |
| if (DefinitionRequired) { |
| if (Function->getPrimaryTemplate()) |
| Diag(PointOfInstantiation, |
| diag::err_explicit_instantiation_undefined_func_template) |
| << Function->getPrimaryTemplate(); |
| else |
| Diag(PointOfInstantiation, |
| diag::err_explicit_instantiation_undefined_member) |
| << 1 << Function->getDeclName() << Function->getDeclContext(); |
| |
| if (PatternDecl) |
| Diag(PatternDecl->getLocation(), |
| diag::note_explicit_instantiation_here); |
| } |
| |
| return; |
| } |
| |
| // C++0x [temp.explicit]p9: |
| // Except for inline functions, other explicit instantiation declarations |
| // have the effect of suppressing the implicit instantiation of the entity |
| // to which they refer. |
| if (Function->getTemplateSpecializationKind() |
| == TSK_ExplicitInstantiationDeclaration && |
| !PatternDecl->isInlined()) |
| return; |
| |
| InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); |
| if (Inst) |
| return; |
| |
| // If we're performing recursive template instantiation, create our own |
| // queue of pending implicit instantiations that we will instantiate later, |
| // while we're still within our own instantiation context. |
| std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations; |
| if (Recursive) |
| PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations); |
| |
| ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function)); |
| |
| // Introduce a new scope where local variable instantiations will be |
| // recorded, unless we're actually a member function within a local |
| // class, in which case we need to merge our results with the parent |
| // scope (of the enclosing function). |
| bool MergeWithParentScope = false; |
| if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext())) |
| MergeWithParentScope = Rec->isLocalClass(); |
| |
| LocalInstantiationScope Scope(*this, MergeWithParentScope); |
| |
| // Introduce the instantiated function parameters into the local |
| // instantiation scope. |
| for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) |
| Scope.InstantiatedLocal(PatternDecl->getParamDecl(I), |
| Function->getParamDecl(I)); |
| |
| // Enter the scope of this instantiation. We don't use |
| // PushDeclContext because we don't have a scope. |
| DeclContext *PreviousContext = CurContext; |
| CurContext = Function; |
| |
| MultiLevelTemplateArgumentList TemplateArgs = |
| getTemplateInstantiationArgs(Function); |
| |
| // If this is a constructor, instantiate the member initializers. |
| if (const CXXConstructorDecl *Ctor = |
| dyn_cast<CXXConstructorDecl>(PatternDecl)) { |
| InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor, |
| TemplateArgs); |
| } |
| |
| // Instantiate the function body. |
| OwningStmtResult Body = SubstStmt(Pattern, TemplateArgs); |
| |
| if (Body.isInvalid()) |
| Function->setInvalidDecl(); |
| |
| ActOnFinishFunctionBody(DeclPtrTy::make(Function), move(Body), |
| /*IsInstantiation=*/true); |
| |
| PerformDependentDiagnostics(PatternDecl, TemplateArgs); |
| |
| CurContext = PreviousContext; |
| |
| DeclGroupRef DG(Function); |
| Consumer.HandleTopLevelDecl(DG); |
| |
| // This class may have local implicit instantiations that need to be |
| // instantiation within this scope. |
| PerformPendingImplicitInstantiations(/*LocalOnly=*/true); |
| Scope.Exit(); |
| |
| if (Recursive) { |
| // Instantiate any pending implicit instantiations found during the |
| // instantiation of this template. |
| PerformPendingImplicitInstantiations(); |
| |
| // Restore the set of pending implicit instantiations. |
| PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations); |
| } |
| } |
| |
| /// \brief Instantiate the definition of the given variable from its |
| /// template. |
| /// |
| /// \param PointOfInstantiation the point at which the instantiation was |
| /// required. Note that this is not precisely a "point of instantiation" |
| /// for the function, but it's close. |
| /// |
| /// \param Var the already-instantiated declaration of a static member |
| /// variable of a class template specialization. |
| /// |
| /// \param Recursive if true, recursively instantiates any functions that |
| /// are required by this instantiation. |
| /// |
| /// \param DefinitionRequired if true, then we are performing an explicit |
| /// instantiation where an out-of-line definition of the member variable |
| /// is required. Complain if there is no such definition. |
| void Sema::InstantiateStaticDataMemberDefinition( |
| SourceLocation PointOfInstantiation, |
| VarDecl *Var, |
| bool Recursive, |
| bool DefinitionRequired) { |
| if (Var->isInvalidDecl()) |
| return; |
| |
| // Find the out-of-line definition of this static data member. |
| VarDecl *Def = Var->getInstantiatedFromStaticDataMember(); |
| assert(Def && "This data member was not instantiated from a template?"); |
| assert(Def->isStaticDataMember() && "Not a static data member?"); |
| Def = Def->getOutOfLineDefinition(); |
| |
| if (!Def) { |
| // We did not find an out-of-line definition of this static data member, |
| // so we won't perform any instantiation. Rather, we rely on the user to |
| // instantiate this definition (or provide a specialization for it) in |
| // another translation unit. |
| if (DefinitionRequired) { |
| Def = Var->getInstantiatedFromStaticDataMember(); |
| Diag(PointOfInstantiation, |
| diag::err_explicit_instantiation_undefined_member) |
| << 2 << Var->getDeclName() << Var->getDeclContext(); |
| Diag(Def->getLocation(), diag::note_explicit_instantiation_here); |
| } |
| |
| return; |
| } |
| |
| // Never instantiate an explicit specialization. |
| if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) |
| return; |
| |
| // C++0x [temp.explicit]p9: |
| // Except for inline functions, other explicit instantiation declarations |
| // have the effect of suppressing the implicit instantiation of the entity |
| // to which they refer. |
| if (Var->getTemplateSpecializationKind() |
| == TSK_ExplicitInstantiationDeclaration) |
| return; |
| |
| InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); |
| if (Inst) |
| return; |
| |
| // If we're performing recursive template instantiation, create our own |
| // queue of pending implicit instantiations that we will instantiate later, |
| // while we're still within our own instantiation context. |
| std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations; |
| if (Recursive) |
| PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations); |
| |
| // Enter the scope of this instantiation. We don't use |
| // PushDeclContext because we don't have a scope. |
| DeclContext *PreviousContext = CurContext; |
| CurContext = Var->getDeclContext(); |
| |
| VarDecl *OldVar = Var; |
| Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(), |
| getTemplateInstantiationArgs(Var))); |
| CurContext = PreviousContext; |
| |
| if (Var) { |
| MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo(); |
| assert(MSInfo && "Missing member specialization information?"); |
| Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(), |
| MSInfo->getPointOfInstantiation()); |
| DeclGroupRef DG(Var); |
| Consumer.HandleTopLevelDecl(DG); |
| } |
| |
| if (Recursive) { |
| // Instantiate any pending implicit instantiations found during the |
| // instantiation of this template. |
| PerformPendingImplicitInstantiations(); |
| |
| // Restore the set of pending implicit instantiations. |
| PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations); |
| } |
| } |
| |
| void |
| Sema::InstantiateMemInitializers(CXXConstructorDecl *New, |
| const CXXConstructorDecl *Tmpl, |
| const MultiLevelTemplateArgumentList &TemplateArgs) { |
| |
| llvm::SmallVector<MemInitTy*, 4> NewInits; |
| bool AnyErrors = false; |
| |
| // Instantiate all the initializers. |
| for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(), |
| InitsEnd = Tmpl->init_end(); |
| Inits != InitsEnd; ++Inits) { |
| CXXBaseOrMemberInitializer *Init = *Inits; |
| |
| SourceLocation LParenLoc, RParenLoc; |
| ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this); |
| llvm::SmallVector<SourceLocation, 4> CommaLocs; |
| |
| // Instantiate the initializer. |
| if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, |
| LParenLoc, CommaLocs, NewArgs, RParenLoc)) { |
| AnyErrors = true; |
| continue; |
| } |
| |
| MemInitResult NewInit; |
| if (Init->isBaseInitializer()) { |
| TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), |
| TemplateArgs, |
| Init->getSourceLocation(), |
| New->getDeclName()); |
| if (!BaseTInfo) { |
| AnyErrors = true; |
| New->setInvalidDecl(); |
| continue; |
| } |
| |
| NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, |
| (Expr **)NewArgs.data(), |
| NewArgs.size(), |
| Init->getLParenLoc(), |
| Init->getRParenLoc(), |
| New->getParent()); |
| } else if (Init->isMemberInitializer()) { |
| FieldDecl *Member; |
| |
| // Is this an anonymous union? |
| if (FieldDecl *UnionInit = Init->getAnonUnionMember()) |
| Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMemberLocation(), |
| UnionInit, TemplateArgs)); |
| else |
| Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMemberLocation(), |
| Init->getMember(), |
| TemplateArgs)); |
| |
| NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), |
| NewArgs.size(), |
| Init->getSourceLocation(), |
| Init->getLParenLoc(), |
| Init->getRParenLoc()); |
| } |
| |
| if (NewInit.isInvalid()) { |
| AnyErrors = true; |
| New->setInvalidDecl(); |
| } else { |
| // FIXME: It would be nice if ASTOwningVector had a release function. |
| NewArgs.take(); |
| |
| NewInits.push_back((MemInitTy *)NewInit.get()); |
| } |
| } |
| |
| // Assign all the initializers to the new constructor. |
| ActOnMemInitializers(DeclPtrTy::make(New), |
| /*FIXME: ColonLoc */ |
| SourceLocation(), |
| NewInits.data(), NewInits.size(), |
| AnyErrors); |
| } |
| |
| // TODO: this could be templated if the various decl types used the |
| // same method name. |
| static bool isInstantiationOf(ClassTemplateDecl *Pattern, |
| ClassTemplateDecl *Instance) { |
| Pattern = Pattern->getCanonicalDecl(); |
| |
| do { |
| Instance = Instance->getCanonicalDecl(); |
| if (Pattern == Instance) return true; |
| Instance = Instance->getInstantiatedFromMemberTemplate(); |
| } while (Instance); |
| |
| return false; |
| } |
| |
| static bool isInstantiationOf(FunctionTemplateDecl *Pattern, |
| FunctionTemplateDecl *Instance) { |
| Pattern = Pattern->getCanonicalDecl(); |
| |
| do { |
| Instance = Instance->getCanonicalDecl(); |
| if (Pattern == Instance) return true; |
| Instance = Instance->getInstantiatedFromMemberTemplate(); |
| } while (Instance); |
| |
| return false; |
| } |
| |
| static bool |
| isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern, |
| ClassTemplatePartialSpecializationDecl *Instance) { |
| Pattern |
| = cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl()); |
| do { |
| Instance = cast<ClassTemplatePartialSpecializationDecl>( |
| Instance->getCanonicalDecl()); |
| if (Pattern == Instance) |
| return true; |
| Instance = Instance->getInstantiatedFromMember(); |
| } while (Instance); |
| |
| return false; |
| } |
| |
| static bool isInstantiationOf(CXXRecordDecl *Pattern, |
| CXXRecordDecl *Instance) { |
| Pattern = Pattern->getCanonicalDecl(); |
| |
| do { |
| Instance = Instance->getCanonicalDecl(); |
| if (Pattern == Instance) return true; |
| Instance = Instance->getInstantiatedFromMemberClass(); |
| } while (Instance); |
| |
| return false; |
| } |
| |
| static bool isInstantiationOf(FunctionDecl *Pattern, |
| FunctionDecl *Instance) { |
| Pattern = Pattern->getCanonicalDecl(); |
| |
| do { |
| Instance = Instance->getCanonicalDecl(); |
| if (Pattern == Instance) return true; |
| Instance = Instance->getInstantiatedFromMemberFunction(); |
| } while (Instance); |
| |
| return false; |
| } |
| |
| static bool isInstantiationOf(EnumDecl *Pattern, |
| EnumDecl *Instance) { |
| Pattern = Pattern->getCanonicalDecl(); |
| |
| do { |
| Instance = Instance->getCanonicalDecl(); |
| if (Pattern == Instance) return true; |
| Instance = Instance->getInstantiatedFromMemberEnum(); |
| } while (Instance); |
| |
| return false; |
| } |
| |
| static bool isInstantiationOf(UsingShadowDecl *Pattern, |
| UsingShadowDecl *Instance, |
| ASTContext &C) { |
| return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern; |
| } |
| |
| static bool isInstantiationOf(UsingDecl *Pattern, |
| UsingDecl *Instance, |
| ASTContext &C) { |
| return C.getInstantiatedFromUsingDecl(Instance) == Pattern; |
| } |
| |
| static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern, |
| UsingDecl *Instance, |
| ASTContext &C) { |
| return C.getInstantiatedFromUsingDecl(Instance) == Pattern; |
| } |
| |
| static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern, |
| UsingDecl *Instance, |
| ASTContext &C) { |
| return C.getInstantiatedFromUsingDecl(Instance) == Pattern; |
| } |
| |
| static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, |
| VarDecl *Instance) { |
| assert(Instance->isStaticDataMember()); |
| |
| Pattern = Pattern->getCanonicalDecl(); |
| |
| do { |
| Instance = Instance->getCanonicalDecl(); |
| if (Pattern == Instance) return true; |
| Instance = Instance->getInstantiatedFromStaticDataMember(); |
| } while (Instance); |
| |
| return false; |
| } |
| |
| // Other is the prospective instantiation |
| // D is the prospective pattern |
| static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { |
| if (D->getKind() != Other->getKind()) { |
| if (UnresolvedUsingTypenameDecl *UUD |
| = dyn_cast<UnresolvedUsingTypenameDecl>(D)) { |
| if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { |
| return isInstantiationOf(UUD, UD, Ctx); |
| } |
| } |
| |
| if (UnresolvedUsingValueDecl *UUD |
| = dyn_cast<UnresolvedUsingValueDecl>(D)) { |
| if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { |
| return isInstantiationOf(UUD, UD, Ctx); |
| } |
| } |
| |
| return false; |
| } |
| |
| if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other)) |
| return isInstantiationOf(cast<CXXRecordDecl>(D), Record); |
| |
| if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other)) |
| return isInstantiationOf(cast<FunctionDecl>(D), Function); |
| |
| if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other)) |
| return isInstantiationOf(cast<EnumDecl>(D), Enum); |
| |
| if (VarDecl *Var = dyn_cast<VarDecl>(Other)) |
| if (Var->isStaticDataMember()) |
| return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var); |
| |
| if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other)) |
| return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp); |
| |
| if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other)) |
| return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp); |
| |
| if (ClassTemplatePartialSpecializationDecl *PartialSpec |
| = dyn_cast<ClassTemplatePartialSpecializationDecl>(Other)) |
| return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D), |
| PartialSpec); |
| |
| if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) { |
| if (!Field->getDeclName()) { |
| // This is an unnamed field. |
| return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) == |
| cast<FieldDecl>(D); |
| } |
| } |
| |
| if (UsingDecl *Using = dyn_cast<UsingDecl>(Other)) |
| return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx); |
| |
| if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other)) |
| return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx); |
| |
| return D->getDeclName() && isa<NamedDecl>(Other) && |
| D->getDeclName() == cast<NamedDecl>(Other)->getDeclName(); |
| } |
| |
| template<typename ForwardIterator> |
| static NamedDecl *findInstantiationOf(ASTContext &Ctx, |
| NamedDecl *D, |
| ForwardIterator first, |
| ForwardIterator last) { |
| for (; first != last; ++first) |
| if (isInstantiationOf(Ctx, D, *first)) |
| return cast<NamedDecl>(*first); |
| |
| return 0; |
| } |
| |
| /// \brief Finds the instantiation of the given declaration context |
| /// within the current instantiation. |
| /// |
| /// \returns NULL if there was an error |
| DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, |
| const MultiLevelTemplateArgumentList &TemplateArgs) { |
| if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) { |
| Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs); |
| return cast_or_null<DeclContext>(ID); |
| } else return DC; |
| } |
| |
| /// \brief Find the instantiation of the given declaration within the |
| /// current instantiation. |
| /// |
| /// This routine is intended to be used when \p D is a declaration |
| /// referenced from within a template, that needs to mapped into the |
| /// corresponding declaration within an instantiation. For example, |
| /// given: |
| /// |
| /// \code |
| /// template<typename T> |
| /// struct X { |
| /// enum Kind { |
| /// KnownValue = sizeof(T) |
| /// }; |
| /// |
| /// bool getKind() const { return KnownValue; } |
| /// }; |
| /// |
| /// template struct X<int>; |
| /// \endcode |
| /// |
| /// In the instantiation of X<int>::getKind(), we need to map the |
| /// EnumConstantDecl for KnownValue (which refers to |
| /// X<T>::<Kind>::KnownValue) to its instantiation |
| /// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs |
| /// this mapping from within the instantiation of X<int>. |
| NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, |
| const MultiLevelTemplateArgumentList &TemplateArgs) { |
| DeclContext *ParentDC = D->getDeclContext(); |
| if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || |
| isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || |
| ParentDC->isFunctionOrMethod()) { |
| // D is a local of some kind. Look into the map of local |
| // declarations to their instantiations. |
| return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D)); |
| } |
| |
| if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { |
| if (!Record->isDependentContext()) |
| return D; |
| |
| // If the RecordDecl is actually the injected-class-name or a |
| // "templated" declaration for a class template, class template |
| // partial specialization, or a member class of a class template, |
| // substitute into the injected-class-name of the class template |
| // or partial specialization to find the new DeclContext. |
| QualType T; |
| ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); |
| |
| if (ClassTemplate) { |
| T = ClassTemplate->getInjectedClassNameSpecialization(Context); |
| } else if (ClassTemplatePartialSpecializationDecl *PartialSpec |
| = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { |
| ClassTemplate = PartialSpec->getSpecializedTemplate(); |
| |
| // If we call SubstType with an InjectedClassNameType here we |
| // can end up in an infinite loop. |
| T = Context.getTypeDeclType(Record); |
| assert(isa<InjectedClassNameType>(T) && |
| "type of partial specialization is not an InjectedClassNameType"); |
| T = cast<InjectedClassNameType>(T)->getUnderlyingType(); |
| } |
| |
| if (!T.isNull()) { |
| // Substitute into the injected-class-name to get the type |
| // corresponding to the instantiation we want, which may also be |
| // the current instantiation (if we're in a template |
| // definition). This substitution should never fail, since we |
| // know we can instantiate the injected-class-name or we |
| // wouldn't have gotten to the injected-class-name! |
| |
| // FIXME: Can we use the CurrentInstantiationScope to avoid this |
| // extra instantiation in the common case? |
| T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName()); |
| assert(!T.isNull() && "Instantiation of injected-class-name cannot fail."); |
| |
| if (!T->isDependentType()) { |
| assert(T->isRecordType() && "Instantiation must produce a record type"); |
| return T->getAs<RecordType>()->getDecl(); |
| } |
| |
| // We are performing "partial" template instantiation to create |
| // the member declarations for the members of a class template |
| // specialization. Therefore, D is actually referring to something |
| // in the current instantiation. Look through the current |
| // context, which contains actual instantiations, to find the |
| // instantiation of the "current instantiation" that D refers |
| // to. |
| bool SawNonDependentContext = false; |
| for (DeclContext *DC = CurContext; !DC->isFileContext(); |
| DC = DC->getParent()) { |
| if (ClassTemplateSpecializationDecl *Spec |
| = dyn_cast<ClassTemplateSpecializationDecl>(DC)) |
| if (isInstantiationOf(ClassTemplate, |
| Spec->getSpecializedTemplate())) |
| return Spec; |
| |
| if (!DC->isDependentContext()) |
| SawNonDependentContext = true; |
| } |
| |
| // We're performing "instantiation" of a member of the current |
| // instantiation while we are type-checking the |
| // definition. Compute the declaration context and return that. |
| assert(!SawNonDependentContext && |
| "No dependent context while instantiating record"); |
| DeclContext *DC = computeDeclContext(T); |
| assert(DC && |
| "Unable to find declaration for the current instantiation"); |
| return cast<CXXRecordDecl>(DC); |
| } |
| |
| // Fall through to deal with other dependent record types (e.g., |
| // anonymous unions in class templates). |
| } |
| |
| if (!ParentDC->isDependentContext()) |
| return D; |
| |
| ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs); |
| if (!ParentDC) |
| return 0; |
| |
| if (ParentDC != D->getDeclContext()) { |
| // We performed some kind of instantiation in the parent context, |
| // so now we need to look into the instantiated parent context to |
| // find the instantiation of the declaration D. |
| |
| // If our context used to be dependent, we may need to instantiate |
| // it before performing lookup into that context. |
| if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) { |
| if (!Spec->isDependentContext()) { |
| QualType T = Context.getTypeDeclType(Spec); |
| const RecordType *Tag = T->getAs<RecordType>(); |
| assert(Tag && "type of non-dependent record is not a RecordType"); |
| if (!Tag->isBeingDefined() && |
| RequireCompleteType(Loc, T, diag::err_incomplete_type)) |
| return 0; |
| } |
| } |
| |
| NamedDecl *Result = 0; |
| if (D->getDeclName()) { |
| DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName()); |
| Result = findInstantiationOf(Context, D, Found.first, Found.second); |
| } else { |
| // Since we don't have a name for the entity we're looking for, |
| // our only option is to walk through all of the declarations to |
| // find that name. This will occur in a few cases: |
| // |
| // - anonymous struct/union within a template |
| // - unnamed class/struct/union/enum within a template |
| // |
| // FIXME: Find a better way to find these instantiations! |
| Result = findInstantiationOf(Context, D, |
| ParentDC->decls_begin(), |
| ParentDC->decls_end()); |
| } |
| |
| // UsingShadowDecls can instantiate to nothing because of using hiding. |
| assert((Result || isa<UsingShadowDecl>(D) || D->isInvalidDecl() || |
| cast<Decl>(ParentDC)->isInvalidDecl()) |
| && "Unable to find instantiation of declaration!"); |
| |
| D = Result; |
| } |
| |
| return D; |
| } |
| |
| /// \brief Performs template instantiation for all implicit template |
| /// instantiations we have seen until this point. |
| void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) { |
| while (!PendingLocalImplicitInstantiations.empty() || |
| (!LocalOnly && !PendingImplicitInstantiations.empty())) { |
| PendingImplicitInstantiation Inst; |
| |
| if (PendingLocalImplicitInstantiations.empty()) { |
| Inst = PendingImplicitInstantiations.front(); |
| PendingImplicitInstantiations.pop_front(); |
| } else { |
| Inst = PendingLocalImplicitInstantiations.front(); |
| PendingLocalImplicitInstantiations.pop_front(); |
| } |
| |
| // Instantiate function definitions |
| if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) { |
| PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Function), |
| Function->getLocation(), *this, |
| Context.getSourceManager(), |
| "instantiating function definition"); |
| |
| if (!Function->getBody()) |
| InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true); |
| continue; |
| } |
| |
| // Instantiate static data member definitions. |
| VarDecl *Var = cast<VarDecl>(Inst.first); |
| assert(Var->isStaticDataMember() && "Not a static data member?"); |
| |
| // Don't try to instantiate declarations if the most recent redeclaration |
| // is invalid. |
| if (Var->getMostRecentDeclaration()->isInvalidDecl()) |
| continue; |
| |
| // Check if the most recent declaration has changed the specialization kind |
| // and removed the need for implicit instantiation. |
| switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) { |
| case TSK_Undeclared: |
| assert(false && "Cannot instantitiate an undeclared specialization."); |
| case TSK_ExplicitInstantiationDeclaration: |
| case TSK_ExplicitInstantiationDefinition: |
| case TSK_ExplicitSpecialization: |
| continue; // No longer need implicit instantiation. |
| case TSK_ImplicitInstantiation: |
| break; |
| } |
| |
| PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Var), |
| Var->getLocation(), *this, |
| Context.getSourceManager(), |
| "instantiating static data member " |
| "definition"); |
| |
| InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true); |
| } |
| } |
| |
| void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, |
| const MultiLevelTemplateArgumentList &TemplateArgs) { |
| for (DeclContext::ddiag_iterator I = Pattern->ddiag_begin(), |
| E = Pattern->ddiag_end(); I != E; ++I) { |
| DependentDiagnostic *DD = *I; |
| |
| switch (DD->getKind()) { |
| case DependentDiagnostic::Access: |
| HandleDependentAccessCheck(*DD, TemplateArgs); |
| break; |
| } |
| } |
| } |