diff options
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 201 |
1 files changed, 110 insertions, 91 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d8af8f34530b1..5109dc8290f92 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -18,11 +18,12 @@ #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/PrettyDeclStackTrace.h" #include "clang/AST/TypeLoc.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" -#include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Template.h" +#include "clang/Sema/TemplateInstCallback.h" using namespace clang; @@ -175,7 +176,8 @@ static void instantiateDependentAllocAlignAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const AllocAlignAttr *Align, Decl *New) { Expr *Param = IntegerLiteral::Create( - S.getASTContext(), llvm::APInt(64, Align->getParamIndex()), + S.getASTContext(), + llvm::APInt(64, Align->getParamIndex().getSourceIndex()), S.getASTContext().UnsignedLongLongTy, Align->getLocation()); S.AddAllocAlignAttr(Align->getLocation(), New, Param, Align->getSpellingListIndex()); @@ -343,14 +345,6 @@ static void instantiateOMPDeclareSimdDeclAttr( Attr.getRange()); } -static bool DeclContainsAttr(const Decl *D, const Attr *NewAttr) { - if (!D->hasAttrs() || NewAttr->duplicatesAllowed()) - return false; - return llvm::find_if(D->getAttrs(), [NewAttr](const Attr *Attr) { - return Attr->getKind() == NewAttr->getKind(); - }) != D->getAttrs().end(); -} - void Sema::InstantiateAttrsForDecl( const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -365,7 +359,7 @@ void Sema::InstantiateAttrsForDecl( Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( TmplAttr, Context, *this, TemplateArgs); - if (NewAttr && !DeclContainsAttr(New, NewAttr)) + if (NewAttr) New->addAttr(NewAttr); } } @@ -470,8 +464,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); - - if (NewAttr && !DeclContainsAttr(New, NewAttr)) + if (NewAttr) New->addAttr(NewAttr); } } @@ -749,7 +742,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, if (D->isNRVOVariable()) { QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType(); - if (SemaRef.isCopyElisionCandidate(ReturnType, Var, false)) + if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict)) Var->setNRVOVariable(true); } @@ -1049,8 +1042,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { SemaRef.SubstType(TI->getType(), TemplateArgs, UnderlyingLoc, DeclarationName()); SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), - DefnUnderlying, - /*EnumUnderlyingIsImplicit=*/false, Enum); + DefnUnderlying, /*IsFixed=*/true, Enum); } } @@ -1126,8 +1118,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition( } SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum, - Enumerators, - nullptr, nullptr); + Enumerators, nullptr, ParsedAttributesView()); } Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { @@ -1564,7 +1555,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { return Record; } -/// \brief Adjust the given function type for an instantiation of the +/// Adjust the given function type for an instantiation of the /// given declaration, to cope with modifications to the function's type that /// aren't reflected in the type-source information. /// @@ -1661,6 +1652,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, NameInfo, T, TInfo, D->getSourceRange().getEnd()); if (DGuide->isCopyDeductionCandidate()) cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate(); + Function->setAccess(D->getAccess()); } else { Function = FunctionDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo, @@ -1815,45 +1807,24 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // apply to non-template function declarations and definitions also apply // to these implicit definitions. if (D->isThisDeclarationADefinition()) { - // Check for a function body. - const FunctionDecl *Definition = nullptr; - if (Function->isDefined(Definition) && - Definition->getTemplateSpecializationKind() == TSK_Undeclared) { - SemaRef.Diag(Function->getLocation(), diag::err_redefinition) - << Function->getDeclName(); - SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition); - } - // Check for redefinitions due to other instantiations of this or - // a similar friend function. - else for (auto R : Function->redecls()) { - if (R == Function) - continue; - - // If some prior declaration of this function has been used, we need - // to instantiate its definition. - if (!QueuedInstantiation && R->isUsed(false)) { - if (MemberSpecializationInfo *MSInfo = - Function->getMemberSpecializationInfo()) { - if (MSInfo->getPointOfInstantiation().isInvalid()) { - SourceLocation Loc = R->getLocation(); // FIXME - MSInfo->setPointOfInstantiation(Loc); - SemaRef.PendingLocalImplicitInstantiations.push_back( - std::make_pair(Function, Loc)); - QueuedInstantiation = true; - } - } - } - - // If some prior declaration of this function was a friend with an - // uninstantiated definition, reject it. - if (R->getFriendObjectKind()) { - if (const FunctionDecl *RPattern = - R->getTemplateInstantiationPattern()) { - if (RPattern->isDefined(RPattern)) { - SemaRef.Diag(Function->getLocation(), diag::err_redefinition) - << Function->getDeclName(); - SemaRef.Diag(R->getLocation(), diag::note_previous_definition); - break; + SemaRef.CheckForFunctionRedefinition(Function); + if (!Function->isInvalidDecl()) { + for (auto R : Function->redecls()) { + if (R == Function) + continue; + + // If some prior declaration of this function has been used, we need + // to instantiate its definition. + if (!QueuedInstantiation && R->isUsed(false)) { + if (MemberSpecializationInfo *MSInfo = + Function->getMemberSpecializationInfo()) { + if (MSInfo->getPointOfInstantiation().isInvalid()) { + SourceLocation Loc = R->getLocation(); // FIXME + MSInfo->setPointOfInstantiation(Loc); + SemaRef.PendingLocalImplicitInstantiations.push_back( + std::make_pair(Function, Loc)); + QueuedInstantiation = true; + } } } } @@ -2676,7 +2647,8 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( NamedDecl *UD = SemaRef.BuildUsingDeclaration( /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), - /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr, + /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, + ParsedAttributesView(), /*IsInstantiation*/ true); if (UD) SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); @@ -2697,9 +2669,9 @@ Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl( Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { SmallVector<NamedDecl*, 8> Expansions; for (auto *UD : D->expansions()) { - if (auto *NewUD = + if (NamedDecl *NewUD = SemaRef.FindInstantiatedDecl(D->getLocation(), UD, TemplateArgs)) - Expansions.push_back(cast<NamedDecl>(NewUD)); + Expansions.push_back(NewUD); else return nullptr; } @@ -2740,6 +2712,8 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( assert(Specialization && "Class scope Specialization is null"); SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD); + // FIXME: If this is a definition, check for redefinition errors! + return NewFD; } @@ -2859,7 +2833,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { Decl * TemplateDeclInstantiator::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { - return VisitFunctionDecl(D, nullptr); + Decl *Inst = VisitFunctionDecl(D, nullptr); + if (Inst && !D->getDescribedFunctionTemplate()) + Owner->addDecl(Inst); + return Inst; } Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) { @@ -3112,7 +3089,7 @@ Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, return Instantiator.Visit(D); } -/// \brief Instantiates a nested template parameter list in the current +/// Instantiates a nested template parameter list in the current /// instantiation context. /// /// \param L The parameter list to instantiate @@ -3148,7 +3125,14 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { return InstL; } -/// \brief Instantiate the declaration of a class template partial +TemplateParameterList * +Sema::SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner, + const MultiLevelTemplateArgumentList &TemplateArgs) { + TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); + return Instantiator.SubstTemplateParams(Params); +} + +/// Instantiate the declaration of a class template partial /// specialization. /// /// \param ClassTemplate the (instantiated) class template that is partially @@ -3282,7 +3266,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( return InstPartialSpec; } -/// \brief Instantiate the declaration of a variable template partial +/// Instantiate the declaration of a variable template partial /// specialization. /// /// \param VarTemplate the (instantiated) variable template that is partially @@ -3624,7 +3608,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, TemplateArgs); } -/// \brief Initializes the common fields of an instantiation function +/// 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 @@ -3657,8 +3641,10 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, assert(FunTmpl->getTemplatedDecl() == Tmpl && "Deduction from the wrong function template?"); (void) FunTmpl; + atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst); ActiveInst.Kind = ActiveInstType::TemplateInstantiation; ActiveInst.Entity = New; + atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst); } } @@ -3710,7 +3696,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, return false; } -/// \brief Initializes common fields of an instantiated method +/// Initializes common fields of an instantiated method /// declaration (New) from the corresponding fields of its template /// (Tmpl). /// @@ -3729,6 +3715,30 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, return false; } +/// Instantiate (or find existing instantiation of) a function template with a +/// given set of template arguments. +/// +/// Usually this should not be used, and template argument deduction should be +/// used in its place. +FunctionDecl * +Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, + const TemplateArgumentList *Args, + SourceLocation Loc) { + FunctionDecl *FD = FTD->getTemplatedDecl(); + + sema::TemplateDeductionInfo Info(Loc); + InstantiatingTemplate Inst( + *this, Loc, FTD, Args->asArray(), + CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info); + if (Inst.isInvalid()) + return nullptr; + + ContextRAII SavedContext(*this, FD); + MultiLevelTemplateArgumentList MArgs(*Args); + + return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs)); +} + /// In the MS ABI, we need to instantiate default arguments of dllexported /// default constructors along with the constructor definition. This allows IR /// gen to emit a constructor closure which calls the default constructor with @@ -3750,7 +3760,7 @@ static void InstantiateDefaultCtorDefaultArgs(Sema &S, } } -/// \brief Instantiate the definition of the given function from its +/// Instantiate the definition of the given function from its /// template. /// /// \param PointOfInstantiation the point at which the instantiation was @@ -3812,7 +3822,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, PendingInstantiations.push_back( std::make_pair(Function, PointOfInstantiation)); } else if (TSK == TSK_ImplicitInstantiation) { - if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { + if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() && + !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) { Diag(PointOfInstantiation, diag::warn_func_template_missing) << Function; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); @@ -3829,8 +3840,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (PatternDecl->isLateTemplateParsed() && !LateTemplateParser) { Function->setInstantiationIsPending(true); - PendingInstantiations.push_back( - std::make_pair(Function, PointOfInstantiation)); + LateParsedInstantiations.push_back( + std::make_pair(Function, PointOfInstantiation)); return; } @@ -3887,7 +3898,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; - PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(), + PrettyDeclStackTraceEntry CrashInfo(Context, Function, SourceLocation(), "instantiating function definition"); // The instantiation is visible here, even if it was first declared in an @@ -3932,8 +3943,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, TemplateArgs)) return; + StmtResult Body; if (PatternDecl->hasSkippedBody()) { ActOnSkippedFunctionBody(Function); + Body = nullptr; } else { if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Function)) { // If this is a constructor, instantiate the member initializers. @@ -3949,16 +3962,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, } // Instantiate the function body. - StmtResult Body = SubstStmt(Pattern, TemplateArgs); + Body = SubstStmt(Pattern, TemplateArgs); if (Body.isInvalid()) Function->setInvalidDecl(); - - // FIXME: finishing the function body while in an expression evaluation - // context seems wrong. Investigate more. - ActOnFinishFunctionBody(Function, Body.get(), - /*IsInstantiation=*/true); } + // FIXME: finishing the function body while in an expression evaluation + // context seems wrong. Investigate more. + ActOnFinishFunctionBody(Function, Body.get(), /*IsInstantiation=*/true); PerformDependentDiagnostics(PatternDecl, TemplateArgs); @@ -4025,7 +4036,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted)); } -/// \brief Instantiates a variable template specialization by completing it +/// Instantiates a variable template specialization by completing it /// with appropriate type information and initializer. VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, @@ -4075,6 +4086,7 @@ void Sema::BuildVariableInstantiation( NewVar->setTSCSpec(OldVar->getTSCSpec()); NewVar->setInitStyle(OldVar->getInitStyle()); NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl()); + NewVar->setObjCForDecl(OldVar->isObjCForDecl()); NewVar->setConstexpr(OldVar->isConstexpr()); NewVar->setInitCapture(OldVar->isInitCapture()); NewVar->setPreviousDeclInSameBlockScope( @@ -4135,7 +4147,8 @@ void Sema::BuildVariableInstantiation( // it right away if the type contains 'auto'. if ((!isa<VarTemplateSpecializationDecl>(NewVar) && !InstantiatingVarTemplate && - !(OldVar->isInline() && OldVar->isThisDeclarationADefinition())) || + !(OldVar->isInline() && OldVar->isThisDeclarationADefinition() && + !NewVar->isThisDeclarationADefinition())) || NewVar->getType()->isUndeducedType()) InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs); @@ -4147,7 +4160,7 @@ void Sema::BuildVariableInstantiation( DiagnoseUnusedDecl(NewVar); } -/// \brief Instantiate the initializer of a variable. +/// Instantiate the initializer of a variable. void Sema::InstantiateVariableInitializer( VarDecl *Var, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs) { @@ -4193,7 +4206,9 @@ void Sema::InstantiateVariableInitializer( Var->setInvalidDecl(); } } else { - if (Var->isStaticDataMember()) { + // `inline` variables are a definition and declaration all in one; we won't + // pick up an initializer from anywhere else. + if (Var->isStaticDataMember() && !Var->isInline()) { if (!Var->isOutOfLine()) return; @@ -4204,14 +4219,17 @@ void Sema::InstantiateVariableInitializer( } // We'll add an initializer to a for-range declaration later. - if (Var->isCXXForRangeDecl()) + if (Var->isCXXForRangeDecl() || Var->isObjCForDecl()) return; ActOnUninitializedDecl(Var); } + + if (getLangOpts().CUDA) + checkAllowedCUDAInitializer(Var); } -/// \brief Instantiate the definition of the given variable from its +/// Instantiate the definition of the given variable from its /// template. /// /// \param PointOfInstantiation the point at which the instantiation was @@ -4295,7 +4313,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; - PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), + PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(), "instantiating variable initializer"); // The instantiation is visible here, even if it was first declared in an @@ -4347,7 +4365,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, std::make_pair(Var, PointOfInstantiation)); } else if (TSK == TSK_ImplicitInstantiation) { // Warn about missing definition at the end of translation unit. - if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { + if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() && + !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) { Diag(PointOfInstantiation, diag::warn_var_template_missing) << Var; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); @@ -4407,7 +4426,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; - PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), + PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(), "instantiating variable definition"); // If we're performing recursive template instantiation, create our own @@ -4829,7 +4848,7 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx, return nullptr; } -/// \brief Finds the instantiation of the given declaration context +/// Finds the instantiation of the given declaration context /// within the current instantiation. /// /// \returns NULL if there was an error @@ -4841,7 +4860,7 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, } else return DC; } -/// \brief Find the instantiation of the given declaration within the +/// Find the instantiation of the given declaration within the /// current instantiation. /// /// This routine is intended to be used when \p D is a declaration @@ -5154,7 +5173,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, return D; } -/// \brief Performs template instantiation for all implicit template +/// Performs template instantiation for all implicit template /// instantiations we have seen until this point. void Sema::PerformPendingInstantiations(bool LocalOnly) { while (!PendingLocalImplicitInstantiations.empty() || @@ -5211,7 +5230,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { break; } - PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), + PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(), "instantiating variable definition"); bool DefinitionRequired = Var->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; |