diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 1422 |
1 files changed, 863 insertions, 559 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 216a64e02380..fbc8572ea0e0 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -9,6 +9,7 @@ // //===----------------------------------------------------------------------===/ +#include "TreeTransform.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" @@ -21,12 +22,15 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" #include "llvm/Support/TimeProfiler.h" +#include <optional> using namespace clang; @@ -91,11 +95,14 @@ static void instantiateDependentAlignedAttr( if (!Result.isInvalid()) S.AddAlignedAttr(New, *Aligned, Result.getAs<Expr>(), IsPackExpansion); } else { - TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(), - TemplateArgs, Aligned->getLocation(), - DeclarationName()); - if (Result) - S.AddAlignedAttr(New, *Aligned, Result, IsPackExpansion); + if (TypeSourceInfo *Result = + S.SubstType(Aligned->getAlignmentType(), TemplateArgs, + Aligned->getLocation(), DeclarationName())) { + if (!S.CheckAlignasTypeArgument(Aligned->getSpelling(), Result, + Aligned->getLocation(), + Result->getTypeLoc().getSourceRange())) + S.AddAlignedAttr(New, *Aligned, Result, IsPackExpansion); + } } } @@ -118,7 +125,7 @@ static void instantiateDependentAlignedAttr( // Determine whether we can expand this attribute pack yet. bool Expand = true, RetainExpansion = false; - Optional<unsigned> NumExpansions; + std::optional<unsigned> NumExpansions; // FIXME: Use the actual location of the ellipsis. SourceLocation EllipsisLoc = Aligned->getLocation(); if (S.CheckParameterPacksForExpansion(EllipsisLoc, Aligned->getRange(), @@ -186,15 +193,37 @@ static void instantiateDependentAnnotationAttr( const AnnotateAttr *Attr, Decl *New) { EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + + // If the attribute has delayed arguments it will have to instantiate those + // and handle them as new arguments for the attribute. + bool HasDelayedArgs = Attr->delayedArgs_size(); + + ArrayRef<Expr *> ArgsToInstantiate = + HasDelayedArgs + ? ArrayRef<Expr *>{Attr->delayedArgs_begin(), Attr->delayedArgs_end()} + : ArrayRef<Expr *>{Attr->args_begin(), Attr->args_end()}; + SmallVector<Expr *, 4> Args; - Args.reserve(Attr->args_size()); - for (auto *E : Attr->args()) { - ExprResult Result = S.SubstExpr(E, TemplateArgs); - if (!Result.isUsable()) + if (S.SubstExprs(ArgsToInstantiate, + /*IsCall=*/false, TemplateArgs, Args)) + return; + + StringRef Str = Attr->getAnnotation(); + if (HasDelayedArgs) { + if (Args.size() < 1) { + S.Diag(Attr->getLoc(), diag::err_attribute_too_few_arguments) + << Attr << 1; return; - Args.push_back(Result.get()); + } + + if (!S.checkStringLiteralArgumentAttr(*Attr, Args[0], Str)) + return; + + llvm::SmallVector<Expr *, 4> ActualArgs; + ActualArgs.insert(ActualArgs.begin(), Args.begin() + 1, Args.end()); + std::swap(Args, ActualArgs); } - S.AddAnnotationAttr(New, *Attr, Attr->getAnnotation(), Args); + S.AddAnnotationAttr(New, *Attr, Str, Args); } static Expr *instantiateDependentFunctionAttrCondition( @@ -273,7 +302,15 @@ static void instantiateDependentCUDALaunchBoundsAttr( MinBlocks = Result.getAs<Expr>(); } - S.AddLaunchBoundsAttr(New, Attr, MaxThreads, MinBlocks); + Expr *MaxBlocks = nullptr; + if (Attr.getMaxBlocks()) { + Result = S.SubstExpr(Attr.getMaxBlocks(), TemplateArgs); + if (Result.isInvalid()) + return; + MaxBlocks = Result.getAs<Expr>(); + } + + S.AddLaunchBoundsAttr(New, Attr, MaxThreads, MinBlocks, MaxBlocks); } static void @@ -434,18 +471,19 @@ static void instantiateOMPDeclareVariantAttr( return; Expr *E = VariantFuncRef.get(); + // Check function/variant ref for `omp declare variant` but not for `omp // begin declare variant` (which use implicit attributes). - Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = - S.checkOpenMPDeclareVariantFunction(S.ConvertDeclToDeclGroup(New), - VariantFuncRef.get(), TI, + std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = + S.checkOpenMPDeclareVariantFunction(S.ConvertDeclToDeclGroup(New), E, TI, + Attr.appendArgs_size(), Attr.getRange()); if (!DeclVarData) return; - E = DeclVarData.getValue().second; - FD = DeclVarData.getValue().first; + E = DeclVarData->second; + FD = DeclVarData->first; if (auto *VariantDRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) { if (auto *VariantFD = dyn_cast<FunctionDecl>(VariantDRE->getDecl())) { @@ -474,12 +512,35 @@ static void instantiateOMPDeclareVariantAttr( SourceLocation(), SubstFD, /* RefersToEnclosingVariableOrCapture */ false, /* NameLoc */ SubstFD->getLocation(), - SubstFD->getType(), ExprValueKind::VK_RValue); + SubstFD->getType(), ExprValueKind::VK_PRValue); } } } - S.ActOnOpenMPDeclareVariantDirective(FD, E, TI, Attr.getRange()); + SmallVector<Expr *, 8> NothingExprs; + SmallVector<Expr *, 8> NeedDevicePtrExprs; + SmallVector<OMPInteropInfo, 4> AppendArgs; + + for (Expr *E : Attr.adjustArgsNothing()) { + ExprResult ER = Subst(E); + if (ER.isInvalid()) + continue; + NothingExprs.push_back(ER.get()); + } + for (Expr *E : Attr.adjustArgsNeedDevicePtr()) { + ExprResult ER = Subst(E); + if (ER.isInvalid()) + continue; + NeedDevicePtrExprs.push_back(ER.get()); + } + for (OMPInteropInfo &II : Attr.appendArgs()) { + // When prefer_type is implemented for append_args handle them here too. + AppendArgs.emplace_back(II.IsTarget, II.IsTargetSync); + } + + S.ActOnOpenMPDeclareVariantDirective( + FD, E, TI, NothingExprs, NeedDevicePtrExprs, AppendArgs, SourceLocation(), + SourceLocation(), Attr.getRange()); } static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( @@ -502,18 +563,16 @@ static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( S.addAMDGPUFlatWorkGroupSizeAttr(New, Attr, MinExpr, MaxExpr); } -static ExplicitSpecifier -instantiateExplicitSpecifier(Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs, - ExplicitSpecifier ES, FunctionDecl *New) { +ExplicitSpecifier Sema::instantiateExplicitSpecifier( + const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES) { if (!ES.getExpr()) return ES; Expr *OldCond = ES.getExpr(); Expr *Cond = nullptr; { EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult SubstResult = S.SubstExpr(OldCond, TemplateArgs); + *this, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult SubstResult = SubstExpr(OldCond, TemplateArgs); if (SubstResult.isInvalid()) { return ExplicitSpecifier::Invalid(); } @@ -521,7 +580,7 @@ instantiateExplicitSpecifier(Sema &S, } ExplicitSpecifier Result(Cond, ES.getKind()); if (!Cond->isTypeDependent()) - S.tryResolveExplicitSpecifier(Result); + tryResolveExplicitSpecifier(Result); return Result; } @@ -548,7 +607,16 @@ static void instantiateDependentAMDGPUWavesPerEUAttr( S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr); } -/// Determine whether the attribute A might be relevent to the declaration D. +// This doesn't take any template parameters, but we have a custom action that +// needs to happen when the kernel itself is instantiated. We need to run the +// ItaniumMangler to mark the names required to name this kernel. +static void instantiateDependentSYCLKernelAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const SYCLKernelAttr &Attr, Decl *New) { + New->addAttr(Attr.clone(S.getASTContext())); +} + +/// Determine whether the attribute A might be relevant to the declaration D. /// If not, we can skip instantiating it. The attribute may or may not have /// been instantiated yet. static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) { @@ -567,9 +635,42 @@ static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) { return true; } + if (const auto *BA = dyn_cast<BuiltinAttr>(A)) { + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + switch (BA->getID()) { + case Builtin::BIforward: + // Do not treat 'std::forward' as a builtin if it takes an rvalue reference + // type and returns an lvalue reference type. The library implementation + // will produce an error in this case; don't get in its way. + if (FD && FD->getNumParams() >= 1 && + FD->getParamDecl(0)->getType()->isRValueReferenceType() && + FD->getReturnType()->isLValueReferenceType()) { + return false; + } + [[fallthrough]]; + case Builtin::BImove: + case Builtin::BImove_if_noexcept: + // HACK: Super-old versions of libc++ (3.1 and earlier) provide + // std::forward and std::move overloads that sometimes return by value + // instead of by reference when building in C++98 mode. Don't treat such + // cases as builtins. + if (FD && !FD->getReturnType()->isReferenceType()) + return false; + break; + } + } + return true; } +static void instantiateDependentHLSLParamModifierAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const HLSLParamModifierAttr *Attr, Decl *New) { + ParmVarDecl *P = cast<ParmVarDecl>(New); + P->addAttr(Attr->clone(S.getASTContext())); + P->setType(S.getASTContext().getLValueReferenceType(P->getType())); +} + void Sema::InstantiateAttrsForDecl( const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -691,6 +792,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, *AMDGPUFlatWorkGroupSize, New); } + if (const auto *ParamAttr = dyn_cast<HLSLParamModifierAttr>(TmplAttr)) { + instantiateDependentHLSLParamModifierAttr(*this, TemplateArgs, ParamAttr, + New); + continue; + } + // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { @@ -723,6 +830,11 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } + if (auto *A = dyn_cast<SYCLKernelAttr>(TmplAttr)) { + instantiateDependentSYCLKernelAttr(*this, TemplateArgs, *A, New); + continue; + } + assert(!TmplAttr->isPackExpansion()); if (TmplAttr->isLateParsed() && LateAttrs) { // Late parsed attributes must be instantiated and attached after the @@ -746,6 +858,22 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, } } +/// Update instantiation attributes after template was late parsed. +/// +/// Some attributes are evaluated based on the body of template. If it is +/// late parsed, such attributes cannot be evaluated when declaration is +/// instantiated. This function is used to update instantiation attributes when +/// template definition is ready. +void Sema::updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst) { + for (const auto *Attr : Pattern->attrs()) { + if (auto *A = dyn_cast<StrictFPAttr>(Attr)) { + if (!Inst->hasAttr<StrictFPAttr>()) + Inst->addAttr(A->clone(getASTContext())); + continue; + } + } +} + /// 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 @@ -762,7 +890,7 @@ void Sema::InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor) { for (unsigned I = 0; I != NumParams; ++I) { (void)CheckCXXDefaultArgExpr(Attr->getLocation(), Ctor, Ctor->getParamDecl(I)); - DiscardCleanupsInEvaluationContext(); + CleanupVarDeclMarking(); } } @@ -789,6 +917,10 @@ TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { llvm_unreachable("Translation units cannot be instantiated"); } +Decl *TemplateDeclInstantiator::VisitHLSLBufferDecl(HLSLBufferDecl *Decl) { + llvm_unreachable("HLSL buffer declarations cannot be instantiated"); +} + Decl * TemplateDeclInstantiator::VisitPragmaCommentDecl(PragmaCommentDecl *D) { llvm_unreachable("pragma comment cannot be instantiated"); @@ -808,6 +940,11 @@ Decl *TemplateDeclInstantiator::VisitMSGuidDecl(MSGuidDecl *D) { llvm_unreachable("GUID declaration cannot be instantiated"); } +Decl *TemplateDeclInstantiator::VisitUnnamedGlobalConstantDecl( + UnnamedGlobalConstantDecl *D) { + llvm_unreachable("UnnamedGlobalConstantDecl cannot be instantiated"); +} + Decl *TemplateDeclInstantiator::VisitTemplateParamObjectDecl( TemplateParamObjectDecl *D) { llvm_unreachable("template parameter objects cannot be instantiated"); @@ -856,10 +993,11 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); } - // HACK: g++ has a bug where it gets the value kind of ?: wrong. - // libstdc++ relies upon this bug in its implementation of common_type. - // If we happen to be processing that implementation, fake up the g++ ?: - // semantics. See LWG issue 2141 for more information on the bug. + // HACK: 2012-10-23 g++ has a bug where it gets the value kind of ?: wrong. + // libstdc++ relies upon this bug in its implementation of common_type. If we + // happen to be processing that implementation, fake up the g++ ?: + // semantics. See LWG issue 2141 for more information on the bug. The bugs + // are fixed in g++ and libstdc++ 4.9.0 (2014-04-22). const DecltypeType *DT = DI->getType()->getAs<DecltypeType>(); CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()); if (DT && RD && isa<ConditionalOperator>(DT->getUnderlyingExpr()) && @@ -914,6 +1052,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, SemaRef.inferGslPointerAttribute(Typedef); Typedef->setAccess(D->getAccess()); + Typedef->setReferenced(D->isReferenced()); return Typedef; } @@ -1050,11 +1189,30 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, StartingScope, InstantiatingVarTemplate); - - if (D->isNRVOVariable()) { - QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType(); - if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict)) - Var->setNRVOVariable(true); + if (D->isNRVOVariable() && !Var->isInvalidDecl()) { + QualType RT; + if (auto *F = dyn_cast<FunctionDecl>(DC)) + RT = F->getReturnType(); + else if (isa<BlockDecl>(DC)) + RT = cast<FunctionType>(SemaRef.getCurBlock()->FunctionType) + ->getReturnType(); + else + llvm_unreachable("Unknown context type"); + + // This is the last chance we have of checking copy elision eligibility + // for functions in dependent contexts. The sema actions for building + // the return statement during template instantiation will have no effect + // regarding copy elision, since NRVO propagation runs on the scope exit + // actions, and these are not run on instantiation. + // This might run through some VarDecls which were returned from non-taken + // 'if constexpr' branches, and these will end up being constructed on the + // return slot even if they will never be returned, as a sort of accidental + // 'optimization'. Notably, functions with 'auto' return types won't have it + // deduced by this point. Coupled with the limitation described + // previously, this makes it very hard to support copy elision for these. + Sema::NamedReturnInfo Info = SemaRef.getNamedReturnInfo(Var); + bool NRVO = SemaRef.getCopyElisionCandidate(Info, RT) != nullptr; + Var->setNRVOVariable(NRVO); } Var->setImplicit(D->isImplicit()); @@ -1062,6 +1220,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, if (Var->isStaticLocal()) SemaRef.CheckStaticLocalForDllExport(Var); + if (Var->getTLSKind()) + SemaRef.CheckThreadLocalForLargeAlignment(Var); + return Var; } @@ -1288,11 +1449,14 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { if (InstantiatedAssertExpr.isInvalid()) return nullptr; - return SemaRef.BuildStaticAssertDeclaration(D->getLocation(), - InstantiatedAssertExpr.get(), - D->getMessage(), - D->getRParenLoc(), - D->isFailed()); + ExprResult InstantiatedMessageExpr = + SemaRef.SubstExpr(D->getMessage(), TemplateArgs); + if (InstantiatedMessageExpr.isInvalid()) + return nullptr; + + return SemaRef.BuildStaticAssertDeclaration( + D->getLocation(), InstantiatedAssertExpr.get(), + InstantiatedMessageExpr.get(), D->getRParenLoc(), D->isFailed()); } Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { @@ -1512,63 +1676,16 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (!PrevClassTemplate && QualifierLoc) { SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) - << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC - << QualifierLoc.getSourceRange(); + << llvm::to_underlying(D->getTemplatedDecl()->getTagKind()) + << Pattern->getDeclName() << DC << QualifierLoc.getSourceRange(); return nullptr; } - - bool AdoptedPreviousTemplateParams = false; - if (PrevClassTemplate) { - bool Complain = true; - - // HACK: libstdc++ 4.2.1 contains an ill-formed friend class - // template for struct std::tr1::__detail::_Map_base, where the - // template parameters of the friend declaration don't match the - // template parameters of the original declaration. In this one - // case, we don't complain about the ill-formed friend - // declaration. - if (isFriend && Pattern->getIdentifier() && - Pattern->getIdentifier()->isStr("_Map_base") && - DC->isNamespace() && - cast<NamespaceDecl>(DC)->getIdentifier() && - cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) { - DeclContext *DCParent = DC->getParent(); - if (DCParent->isNamespace() && - cast<NamespaceDecl>(DCParent)->getIdentifier() && - cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) { - if (cast<Decl>(DCParent)->isInStdNamespace()) - Complain = false; - } - } - - TemplateParameterList *PrevParams - = PrevClassTemplate->getMostRecentDecl()->getTemplateParameters(); - - // Make sure the parameter lists match. - if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, - Complain, - Sema::TPL_TemplateMatch)) { - if (Complain) - return nullptr; - - AdoptedPreviousTemplateParams = true; - InstParams = PrevParams; - } - - // Do some additional validation, then merge default arguments - // from the existing declarations. - if (!AdoptedPreviousTemplateParams && - SemaRef.CheckTemplateParameterList(InstParams, PrevParams, - Sema::TPC_ClassTemplate)) - return nullptr; - } } CXXRecordDecl *RecordInst = CXXRecordDecl::Create( SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getBeginLoc(), Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl, /*DelayTypeCreation=*/true); - if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); @@ -1578,16 +1695,38 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, RecordInst); - assert(!(isFriend && Owner->isDependentContext())); - Inst->setPreviousDecl(PrevClassTemplate); - RecordInst->setDescribedClassTemplate(Inst); if (isFriend) { - if (PrevClassTemplate) + assert(!Owner->isDependentContext()); + Inst->setLexicalDeclContext(Owner); + RecordInst->setLexicalDeclContext(Owner); + + if (PrevClassTemplate) { + Inst->setCommonPtr(PrevClassTemplate->getCommonPtr()); + RecordInst->setTypeForDecl( + PrevClassTemplate->getTemplatedDecl()->getTypeForDecl()); + const ClassTemplateDecl *MostRecentPrevCT = + PrevClassTemplate->getMostRecentDecl(); + TemplateParameterList *PrevParams = + MostRecentPrevCT->getTemplateParameters(); + + // Make sure the parameter lists match. + if (!SemaRef.TemplateParameterListsAreEqual( + RecordInst, InstParams, MostRecentPrevCT->getTemplatedDecl(), + PrevParams, true, Sema::TPL_TemplateMatch)) + return nullptr; + + // Do some additional validation, then merge default arguments + // from the existing declarations. + if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams, + Sema::TPC_ClassTemplate)) + return nullptr; + Inst->setAccess(PrevClassTemplate->getAccess()); - else + } else { Inst->setAccess(D->getAccess()); + } Inst->setObjectOfFriendDecl(); // TODO: do we want to track the instantiation progeny of this @@ -1598,15 +1737,15 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Inst->setInstantiatedFromMemberTemplate(D); } + Inst->setPreviousDecl(PrevClassTemplate); + // Trigger creation of the type for the instantiation. - SemaRef.Context.getInjectedClassNameType(RecordInst, - Inst->getInjectedClassNameSpecialization()); + SemaRef.Context.getInjectedClassNameType( + RecordInst, Inst->getInjectedClassNameSpecialization()); // Finish handling of friends. if (isFriend) { DC->makeDeclVisibleInContext(Inst); - Inst->setLexicalDeclContext(Owner); - RecordInst->setLexicalDeclContext(Owner); return Inst; } @@ -1743,6 +1882,7 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // merged with the local instantiation scope for the function template // itself. LocalInstantiationScope Scope(SemaRef); + Sema::ConstraintEvalRAII<TemplateDeclInstantiator> RAII(*this); TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); @@ -1790,9 +1930,7 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *PrevDecl = nullptr; - if (D->isInjectedClassName()) - PrevDecl = cast<CXXRecordDecl>(Owner); - else if (CXXRecordDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { + if (CXXRecordDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), PatternPrev, TemplateArgs); @@ -1800,9 +1938,21 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { PrevDecl = cast<CXXRecordDecl>(Prev); } - CXXRecordDecl *Record = CXXRecordDecl::Create( - SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), - D->getLocation(), D->getIdentifier(), PrevDecl); + CXXRecordDecl *Record = nullptr; + bool IsInjectedClassName = D->isInjectedClassName(); + if (D->isLambda()) + Record = CXXRecordDecl::CreateLambda( + SemaRef.Context, Owner, D->getLambdaTypeInfo(), D->getLocation(), + D->getLambdaDependencyKind(), D->isGenericLambda(), + D->getLambdaCaptureDefault()); + else + Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, + D->getBeginLoc(), D->getLocation(), + D->getIdentifier(), PrevDecl, + /*DelayTypeCreation=*/IsInjectedClassName); + // Link the type of the injected-class-name to that of the outer class. + if (IsInjectedClassName) + (void)SemaRef.Context.getTypeDeclType(Record, cast<CXXRecordDecl>(Owner)); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Record)) @@ -1817,7 +1967,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { // specifier. Remove once this area of the code gets sorted out. if (D->getAccess() != AS_none) Record->setAccess(D->getAccess()); - if (!D->isInjectedClassName()) + if (!IsInjectedClassName) Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); // If the original function was part of a friend declaration, @@ -1870,6 +2020,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { SemaRef.DiagnoseUnusedNestedTypedefs(Record); + if (IsInjectedClassName) + assert(Record->isInjectedClassName() && "Broken injected-class-name"); + return Record; } @@ -1898,7 +2051,7 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, /// Normal class members are of more specific types and therefore /// don't make it here. This function serves three purposes: /// 1) instantiating function templates -/// 2) substituting friend declarations +/// 2) substituting friend and local function declarations /// 3) substituting deduction guide declarations for nested class templates Decl *TemplateDeclInstantiator::VisitFunctionDecl( FunctionDecl *D, TemplateParameterList *TemplateParams, @@ -1932,8 +2085,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( ExplicitSpecifier InstantiatedExplicitSpecifier; if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { - InstantiatedExplicitSpecifier = instantiateExplicitSpecifier( - SemaRef, TemplateArgs, DGuide->getExplicitSpecifier(), DGuide); + InstantiatedExplicitSpecifier = SemaRef.instantiateExplicitSpecifier( + TemplateArgs, DGuide->getExplicitSpecifier()); if (InstantiatedExplicitSpecifier.isInvalid()) return nullptr; } @@ -1969,19 +2122,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( return nullptr; } - // FIXME: Concepts: Do not substitute into constraint expressions Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); - if (TrailingRequiresClause) { - EnterExpressionEvaluationContext ConstantEvaluated( - SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); - ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, - TemplateArgs); - if (SubstRC.isInvalid()) - return nullptr; - TrailingRequiresClause = SubstRC.get(); - if (!SemaRef.CheckConstraintExpression(TrailingRequiresClause)) - return nullptr; - } // If we're instantiating a local function declaration, put the result // in the enclosing namespace; otherwise we need to find the instantiated @@ -2011,16 +2152,17 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( Function = CXXDeductionGuideDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), InstantiatedExplicitSpecifier, NameInfo, T, TInfo, - D->getSourceRange().getEnd()); - if (DGuide->isCopyDeductionCandidate()) - cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate(); + D->getSourceRange().getEnd(), DGuide->getCorrespondingConstructor(), + DGuide->getDeductionCandidateKind()); Function->setAccess(D->getAccess()); } else { Function = FunctionDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo, - D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(), - D->hasWrittenPrototype(), D->getConstexprKind(), + D->getCanonicalDecl()->getStorageClass(), D->UsesFPIntrin(), + D->isInlineSpecified(), D->hasWrittenPrototype(), D->getConstexprKind(), TrailingRequiresClause); + Function->setFriendConstraintRefersToEnclosingTemplate( + D->FriendConstraintRefersToEnclosingTemplate()); Function->setRangeEnd(D->getSourceRange().getEnd()); } @@ -2038,6 +2180,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( assert(D->getDeclContext()->isFileContext()); LexicalDC = D->getDeclContext(); } + else if (D->isLocalExternDecl()) { + LexicalDC = SemaRef.CurContext; + } Function->setLexicalDeclContext(LexicalDC); @@ -2089,6 +2234,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( // definition. We don't want non-template functions to be marked as being // template instantiations. Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); + } else if (!isFriend) { + // If this is not a function template, and this is not a friend (that is, + // this is a locally declared function), save the instantiation relationship + // for the purposes of constraint instantiation. + Function->setInstantiatedFromDecl(D); } if (isFriend) { @@ -2109,43 +2259,47 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( D->isLocalExternDecl() ? Sema::ForExternalRedeclaration : SemaRef.forRedeclarationInCurContext()); - if (DependentFunctionTemplateSpecializationInfo *Info - = D->getDependentSpecializationInfo()) { - assert(isFriend && "non-friend has dependent specialization info?"); + if (DependentFunctionTemplateSpecializationInfo *DFTSI = + D->getDependentSpecializationInfo()) { + assert(isFriend && "dependent specialization info on " + "non-member non-friend function?"); // Instantiate the explicit template arguments. - TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), - Info->getRAngleLoc()); - if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), - ExplicitArgs, TemplateArgs)) - return nullptr; - - // Map the candidate templates to their instantiations. - for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { - Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), - Info->getTemplate(I), - TemplateArgs); - if (!Temp) return nullptr; + TemplateArgumentListInfo ExplicitArgs; + if (const auto *ArgsWritten = DFTSI->TemplateArgumentsAsWritten) { + ExplicitArgs.setLAngleLoc(ArgsWritten->getLAngleLoc()); + ExplicitArgs.setRAngleLoc(ArgsWritten->getRAngleLoc()); + if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs, + ExplicitArgs)) + return nullptr; + } - Previous.addDecl(cast<FunctionTemplateDecl>(Temp)); + // Map the candidates for the primary template to their instantiations. + for (FunctionTemplateDecl *FTD : DFTSI->getCandidates()) { + if (NamedDecl *ND = + SemaRef.FindInstantiatedDecl(D->getLocation(), FTD, TemplateArgs)) + Previous.addDecl(ND); + else + return nullptr; } - if (SemaRef.CheckFunctionTemplateSpecialization(Function, - &ExplicitArgs, - Previous)) + if (SemaRef.CheckFunctionTemplateSpecialization( + Function, + DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr, + Previous)) Function->setInvalidDecl(); IsExplicitSpecialization = true; - } else if (const ASTTemplateArgumentListInfo *Info = + } else if (const ASTTemplateArgumentListInfo *ArgsWritten = D->getTemplateSpecializationArgsAsWritten()) { // The name of this function was written as a template-id. SemaRef.LookupQualifiedName(Previous, DC); // Instantiate the explicit template arguments. - TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), - Info->getRAngleLoc()); - if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), - ExplicitArgs, TemplateArgs)) + TemplateArgumentListInfo ExplicitArgs(ArgsWritten->getLAngleLoc(), + ArgsWritten->getRAngleLoc()); + if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs, + ExplicitArgs)) return nullptr; if (SemaRef.CheckFunctionTemplateSpecialization(Function, @@ -2162,7 +2316,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( // 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 + // tag type. Note that this does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). if (Previous.isSingleTagDecl()) Previous.clear(); @@ -2170,13 +2324,47 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( // Filter out previous declarations that don't match the scope. The only // effect this has is to remove declarations found in inline namespaces // for friend declarations with unqualified names. - SemaRef.FilterLookupForScope(Previous, DC, /*Scope*/ nullptr, - /*ConsiderLinkage*/ true, - QualifierLoc.hasQualifier()); + if (isFriend && !QualifierLoc) { + SemaRef.FilterLookupForScope(Previous, DC, /*Scope=*/ nullptr, + /*ConsiderLinkage=*/ true, + QualifierLoc.hasQualifier()); + } + } + + // Per [temp.inst], default arguments in function declarations at local scope + // are instantiated along with the enclosing declaration. For example: + // + // template<typename T> + // void ft() { + // void f(int = []{ return T::value; }()); + // } + // template void ft<int>(); // error: type 'int' cannot be used prior + // to '::' because it has no members + // + // The error is issued during instantiation of ft<int>() because substitution + // into the default argument fails; the default argument is instantiated even + // though it is never used. + if (Function->isLocalExternDecl()) { + for (ParmVarDecl *PVD : Function->parameters()) { + if (!PVD->hasDefaultArg()) + continue; + if (SemaRef.SubstDefaultArgument(D->getInnerLocStart(), PVD, TemplateArgs)) { + // If substitution fails, the default argument is set to a + // RecoveryExpr that wraps the uninstantiated default argument so + // that downstream diagnostics are omitted. + Expr *UninstExpr = PVD->getUninstantiatedDefaultArg(); + ExprResult ErrorResult = SemaRef.CreateRecoveryExpr( + UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), + { UninstExpr }, UninstExpr->getType()); + if (ErrorResult.isUsable()) + PVD->setDefaultArg(ErrorResult.get()); + } + } } SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous, - IsExplicitSpecialization); + IsExplicitSpecialization, + Function->isThisDeclarationADefinition()); // Check the template parameter list against the previous declaration. The // goal here is to pick up default arguments added since the friend was @@ -2232,7 +2420,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( CXXMethodDecl *D, TemplateParameterList *TemplateParams, - Optional<const ASTTemplateArgumentListInfo *> ClassScopeSpecializationArgs, RewriteKind FunctionRewriteKind) { FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); if (FunctionTemplate && !TemplateParams) { @@ -2261,6 +2448,9 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); + Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope( + SemaRef, const_cast<CXXMethodDecl *>(D), TemplateArgs, Scope); + // Instantiate enclosing template arguments for friends. SmallVector<TemplateParameterList *, 4> TempParamLists; unsigned NumTempParamLists = 0; @@ -2275,11 +2465,39 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( } } - ExplicitSpecifier InstantiatedExplicitSpecifier = - instantiateExplicitSpecifier(SemaRef, TemplateArgs, - ExplicitSpecifier::getFromDecl(D), D); - if (InstantiatedExplicitSpecifier.isInvalid()) - return nullptr; + auto InstantiatedExplicitSpecifier = ExplicitSpecifier::getFromDecl(D); + // deduction guides need this + const bool CouldInstantiate = + InstantiatedExplicitSpecifier.getExpr() == nullptr || + !InstantiatedExplicitSpecifier.getExpr()->isValueDependent(); + + // Delay the instantiation of the explicit-specifier until after the + // constraints are checked during template argument deduction. + if (CouldInstantiate || + SemaRef.CodeSynthesisContexts.back().Kind != + Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution) { + InstantiatedExplicitSpecifier = SemaRef.instantiateExplicitSpecifier( + TemplateArgs, InstantiatedExplicitSpecifier); + + if (InstantiatedExplicitSpecifier.isInvalid()) + return nullptr; + } else { + InstantiatedExplicitSpecifier.setKind(ExplicitSpecKind::Unresolved); + } + + // Implicit destructors/constructors created for local classes in + // DeclareImplicit* (see SemaDeclCXX.cpp) might not have an associated TSI. + // Unfortunately there isn't enough context in those functions to + // conditionally populate the TSI without breaking non-template related use + // cases. Populate TSIs prior to calling SubstFunctionType to make sure we get + // a proper transformation. + if (cast<CXXRecordDecl>(D->getParent())->isLambda() && + !D->getTypeSourceInfo() && + isa<CXXConstructorDecl, CXXDestructorDecl>(D)) { + TypeSourceInfo *TSI = + SemaRef.Context.getTrivialTypeSourceInfo(D->getType()); + D->setTypeSourceInfo(TSI); + } SmallVector<ParmVarDecl *, 4> Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); @@ -2312,23 +2530,6 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( return nullptr; } - // FIXME: Concepts: Do not substitute into constraint expressions - Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); - if (TrailingRequiresClause) { - EnterExpressionEvaluationContext ConstantEvaluated( - SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); - auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); - Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, - D->getMethodQualifiers(), ThisContext); - ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, - TemplateArgs); - if (SubstRC.isInvalid()) - return nullptr; - TrailingRequiresClause = SubstRC.get(); - if (!SemaRef.CheckConstraintExpression(TrailingRequiresClause)) - return nullptr; - } - DeclContext *DC = Owner; if (isFriend) { if (QualifierLoc) { @@ -2346,6 +2547,9 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( if (!DC) return nullptr; } + CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); + Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); + DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); @@ -2353,35 +2557,39 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( adjustForRewrite(FunctionRewriteKind, D, T, TInfo, NameInfo); // Build the instantiated method declaration. - CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); CXXMethodDecl *Method = nullptr; SourceLocation StartLoc = D->getInnerLocStart(); if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { Method = CXXConstructorDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false, + InstantiatedExplicitSpecifier, Constructor->UsesFPIntrin(), + Constructor->isInlineSpecified(), false, Constructor->getConstexprKind(), InheritedConstructor(), TrailingRequiresClause); Method->setRangeEnd(Constructor->getEndLoc()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - Destructor->isInlineSpecified(), false, Destructor->getConstexprKind(), - TrailingRequiresClause); + Destructor->UsesFPIntrin(), Destructor->isInlineSpecified(), false, + Destructor->getConstexprKind(), TrailingRequiresClause); + Method->setIneligibleOrNotSelected(true); Method->setRangeEnd(Destructor->getEndLoc()); + Method->setDeclName(SemaRef.Context.DeclarationNames.getCXXDestructorName( + SemaRef.Context.getCanonicalType( + SemaRef.Context.getTypeDeclType(Record)))); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { Method = CXXConversionDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier, - Conversion->getConstexprKind(), Conversion->getEndLoc(), - TrailingRequiresClause); + Conversion->UsesFPIntrin(), Conversion->isInlineSpecified(), + InstantiatedExplicitSpecifier, Conversion->getConstexprKind(), + Conversion->getEndLoc(), TrailingRequiresClause); } else { StorageClass SC = D->isStatic() ? SC_Static : SC_None; - Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, - T, TInfo, SC, D->isInlineSpecified(), - D->getConstexprKind(), D->getEndLoc(), - TrailingRequiresClause); + Method = CXXMethodDecl::Create( + SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, SC, + D->UsesFPIntrin(), D->isInlineSpecified(), D->getConstexprKind(), + D->getEndLoc(), TrailingRequiresClause); } if (D->isInlined()) @@ -2433,7 +2641,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( if (NumTempParamLists) Method->setTemplateParameterListsInfo( SemaRef.Context, - llvm::makeArrayRef(TempParamLists.data(), NumTempParamLists)); + llvm::ArrayRef(TempParamLists.data(), NumTempParamLists)); Method->setLexicalDeclContext(Owner); Method->setObjectOfFriendDecl(); @@ -2455,42 +2663,42 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( // If the name of this function was written as a template-id, instantiate // the explicit template arguments. - if (DependentFunctionTemplateSpecializationInfo *Info - = D->getDependentSpecializationInfo()) { - assert(isFriend && "non-friend has dependent specialization info?"); - + if (DependentFunctionTemplateSpecializationInfo *DFTSI = + D->getDependentSpecializationInfo()) { // Instantiate the explicit template arguments. - TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), - Info->getRAngleLoc()); - if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), - ExplicitArgs, TemplateArgs)) - return nullptr; - - // Map the candidate templates to their instantiations. - for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { - Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), - Info->getTemplate(I), - TemplateArgs); - if (!Temp) return nullptr; + TemplateArgumentListInfo ExplicitArgs; + if (const auto *ArgsWritten = DFTSI->TemplateArgumentsAsWritten) { + ExplicitArgs.setLAngleLoc(ArgsWritten->getLAngleLoc()); + ExplicitArgs.setRAngleLoc(ArgsWritten->getRAngleLoc()); + if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs, + ExplicitArgs)) + return nullptr; + } - Previous.addDecl(cast<FunctionTemplateDecl>(Temp)); + // Map the candidates for the primary template to their instantiations. + for (FunctionTemplateDecl *FTD : DFTSI->getCandidates()) { + if (NamedDecl *ND = + SemaRef.FindInstantiatedDecl(D->getLocation(), FTD, TemplateArgs)) + Previous.addDecl(ND); + else + return nullptr; } - if (SemaRef.CheckFunctionTemplateSpecialization(Method, - &ExplicitArgs, - Previous)) + if (SemaRef.CheckFunctionTemplateSpecialization( + Method, DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr, + Previous)) Method->setInvalidDecl(); IsExplicitSpecialization = true; - } else if (const ASTTemplateArgumentListInfo *Info = - ClassScopeSpecializationArgs.getValueOr( - D->getTemplateSpecializationArgsAsWritten())) { + } else if (const ASTTemplateArgumentListInfo *ArgsWritten = + D->getTemplateSpecializationArgsAsWritten()) { SemaRef.LookupQualifiedName(Previous, DC); - TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), - Info->getRAngleLoc()); - if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), - ExplicitArgs, TemplateArgs)) + TemplateArgumentListInfo ExplicitArgs(ArgsWritten->getLAngleLoc(), + ArgsWritten->getRAngleLoc()); + + if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs, + ExplicitArgs)) return nullptr; if (SemaRef.CheckFunctionTemplateSpecialization(Method, @@ -2499,29 +2707,55 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( Method->setInvalidDecl(); IsExplicitSpecialization = true; - } else if (ClassScopeSpecializationArgs) { - // Class-scope explicit specialization written without explicit template - // arguments. - SemaRef.LookupQualifiedName(Previous, DC); - if (SemaRef.CheckFunctionTemplateSpecialization(Method, nullptr, Previous)) - Method->setInvalidDecl(); - - IsExplicitSpecialization = true; } else if (!FunctionTemplate || TemplateParams || isFriend) { SemaRef.LookupQualifiedName(Previous, Record); // 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 + // tag type. Note that this does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). if (Previous.isSingleTagDecl()) Previous.clear(); } + // Per [temp.inst], default arguments in member functions of local classes + // are instantiated along with the member function declaration. For example: + // + // template<typename T> + // void ft() { + // struct lc { + // int operator()(int p = []{ return T::value; }()); + // }; + // } + // template void ft<int>(); // error: type 'int' cannot be used prior + // to '::'because it has no members + // + // The error is issued during instantiation of ft<int>()::lc::operator() + // because substitution into the default argument fails; the default argument + // is instantiated even though it is never used. + if (D->isInLocalScopeForInstantiation()) { + for (unsigned P = 0; P < Params.size(); ++P) { + if (!Params[P]->hasDefaultArg()) + continue; + if (SemaRef.SubstDefaultArgument(StartLoc, Params[P], TemplateArgs)) { + // If substitution fails, the default argument is set to a + // RecoveryExpr that wraps the uninstantiated default argument so + // that downstream diagnostics are omitted. + Expr *UninstExpr = Params[P]->getUninstantiatedDefaultArg(); + ExprResult ErrorResult = SemaRef.CreateRecoveryExpr( + UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), + { UninstExpr }, UninstExpr->getType()); + if (ErrorResult.isUsable()) + Params[P]->setDefaultArg(ErrorResult.get()); + } + } + } + SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, - IsExplicitSpecialization); + IsExplicitSpecialization, + Method->isThisDeclarationADefinition()); - if (D->isPure()) + if (D->isPureVirtual()) SemaRef.CheckPureMethod(Method, SourceRange()); // Propagate access. For a non-friend declaration, the access is @@ -2550,6 +2784,22 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( if (IsExplicitSpecialization && !isFriend) SemaRef.CompleteMemberSpecialization(Method, Previous); + // If the method is a special member function, we need to mark it as + // ineligible so that Owner->addDecl() won't mark the class as non trivial. + // At the end of the class instantiation, we calculate eligibility again and + // then we adjust trivility if needed. + // We need this check to happen only after the method parameters are set, + // because being e.g. a copy constructor depends on the instantiated + // arguments. + if (auto *Constructor = dyn_cast<CXXConstructorDecl>(Method)) { + if (Constructor->isDefaultConstructor() || + Constructor->isCopyOrMoveConstructor()) + Method->setIneligibleOrNotSelected(true); + } else if (Method->isCopyAssignmentOperator() || + Method->isMoveAssignmentOperator()) { + Method->setIneligibleOrNotSelected(true); + } + // If there's a function template, let our caller handle it. if (FunctionTemplate) { // do nothing @@ -2604,16 +2854,16 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { } Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, None, - /*ExpectParameterPack=*/ false); + return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, + std::nullopt, + /*ExpectParameterPack=*/false); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *D) { - // TODO: don't always clone when decls are refcounted. assert(D->getTypeForDecl()->isTemplateTypeParmType()); - Optional<unsigned> NumExpanded; + std::optional<unsigned> NumExpanded; if (const TypeConstraint *TC = D->getTypeConstraint()) { if (D->isPackExpansion() && !D->isExpandedParameterPack()) { @@ -2653,31 +2903,11 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( Inst->setImplicit(D->isImplicit()); if (auto *TC = D->getTypeConstraint()) { if (!D->isImplicit()) { - // Invented template parameter type constraints will be instantiated with - // the corresponding auto-typed parameter as it might reference other - // parameters. - - // TODO: Concepts: do not instantiate the constraint (delayed constraint - // substitution) - const ASTTemplateArgumentListInfo *TemplArgInfo - = TC->getTemplateArgsAsWritten(); - TemplateArgumentListInfo InstArgs; - - if (TemplArgInfo) { - InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); - InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); - if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), - TemplArgInfo->NumTemplateArgs, - InstArgs, TemplateArgs)) - return nullptr; - } - if (SemaRef.AttachTypeConstraint( - TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), - TC->getNamedConcept(), &InstArgs, Inst, - D->isParameterPack() - ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) - ->getEllipsisLoc() - : SourceLocation())) + // Invented template parameter type constraints will be instantiated + // with the corresponding auto-typed parameter as it might reference + // other parameters. + if (SemaRef.SubstTypeConstraint(Inst, TC, TemplateArgs, + EvaluateConstraints)) return nullptr; } } @@ -2744,9 +2974,9 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( // be expanded. bool Expand = true; bool RetainExpansion = false; - Optional<unsigned> OrigNumExpansions - = Expansion.getTypePtr()->getNumExpansions(); - Optional<unsigned> NumExpansions = OrigNumExpansions; + std::optional<unsigned> OrigNumExpansions = + Expansion.getTypePtr()->getNumExpansions(); + std::optional<unsigned> NumExpansions = OrigNumExpansions; if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(), Pattern.getSourceRange(), Unexpanded, @@ -2826,14 +3056,21 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI); if (AutoTypeLoc AutoLoc = DI->getTypeLoc().getContainedAutoTypeLoc()) - if (AutoLoc.isConstrained()) - if (SemaRef.AttachTypeConstraint( - AutoLoc, Param, - IsExpandedParameterPack - ? DI->getTypeLoc().getAs<PackExpansionTypeLoc>() - .getEllipsisLoc() - : SourceLocation())) + if (AutoLoc.isConstrained()) { + SourceLocation EllipsisLoc; + if (IsExpandedParameterPack) + EllipsisLoc = + DI->getTypeLoc().getAs<PackExpansionTypeLoc>().getEllipsisLoc(); + else if (auto *Constraint = dyn_cast_if_present<CXXFoldExpr>( + D->getPlaceholderTypeConstraint())) + EllipsisLoc = Constraint->getEllipsisLoc(); + // Note: We attach the uninstantiated constriant here, so that it can be + // instantiated relative to the top level, like all our other + // constraints. + if (SemaRef.AttachTypeConstraint(AutoLoc, /*NewConstrainedParm=*/Param, + /*OrigConstrainedParm=*/D, EllipsisLoc)) Invalid = true; + } Param->setAccess(AS_public); Param->setImplicit(D->isImplicit()); @@ -2909,7 +3146,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( // be expanded. bool Expand = true; bool RetainExpansion = false; - Optional<unsigned> NumExpansions; + std::optional<unsigned> NumExpansions; if (SemaRef.CheckParameterPacksForExpansion(D->getLocation(), TempParams->getSourceRange(), Unexpanded, @@ -3009,6 +3246,53 @@ Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { return Inst; } +Decl *TemplateDeclInstantiator::VisitBaseUsingDecls(BaseUsingDecl *D, + BaseUsingDecl *Inst, + LookupResult *Lookup) { + + bool isFunctionScope = Owner->isFunctionOrMethod(); + + for (auto *Shadow : D->shadows()) { + // FIXME: UsingShadowDecl doesn't preserve its immediate target, so + // reconstruct it in the case where it matters. Hm, can we extract it from + // the DeclSpec when parsing and save it in the UsingDecl itself? + NamedDecl *OldTarget = Shadow->getTargetDecl(); + if (auto *CUSD = dyn_cast<ConstructorUsingShadowDecl>(Shadow)) + if (auto *BaseShadow = CUSD->getNominatedBaseClassShadowDecl()) + OldTarget = BaseShadow; + + NamedDecl *InstTarget = nullptr; + if (auto *EmptyD = + dyn_cast<UnresolvedUsingIfExistsDecl>(Shadow->getTargetDecl())) { + InstTarget = UnresolvedUsingIfExistsDecl::Create( + SemaRef.Context, Owner, EmptyD->getLocation(), EmptyD->getDeclName()); + } else { + InstTarget = cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), OldTarget, TemplateArgs)); + } + if (!InstTarget) + return nullptr; + + UsingShadowDecl *PrevDecl = nullptr; + if (Lookup && + SemaRef.CheckUsingShadowDecl(Inst, InstTarget, *Lookup, PrevDecl)) + continue; + + if (UsingShadowDecl *OldPrev = getPreviousDeclForInstantiation(Shadow)) + PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), OldPrev, TemplateArgs)); + + UsingShadowDecl *InstShadow = SemaRef.BuildUsingShadowDecl( + /*Scope*/ nullptr, Inst, InstTarget, PrevDecl); + SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); + + if (isFunctionScope) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); + } + + return Inst; +} + Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { // The nested name specifier may be dependent, for example @@ -3034,11 +3318,9 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { NameInfo.setName(SemaRef.Context.DeclarationNames.getCXXConstructorName( SemaRef.Context.getCanonicalType(SemaRef.Context.getRecordType(RD)))); - // 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). + // 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, NameInfo, Sema::LookupUsingDeclName, Sema::ForVisibleRedeclaration); @@ -3059,12 +3341,11 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { D->hasTypename(), SS, D->getLocation(), Prev)) NewUD->setInvalidDecl(); - } if (!NewUD->isInvalidDecl() && - SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(), - SS, NameInfo, D->getLocation())) + SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(), SS, + NameInfo, D->getLocation(), nullptr, D)) NewUD->setInvalidDecl(); SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D); @@ -3075,46 +3356,41 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { if (NewUD->isInvalidDecl()) return NewUD; + // If the using scope was dependent, or we had dependent bases, we need to + // recheck the inheritance if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) SemaRef.CheckInheritingConstructorUsingDecl(NewUD); - bool isFunctionScope = Owner->isFunctionOrMethod(); + return VisitBaseUsingDecls(D, NewUD, CheckRedeclaration ? &Prev : nullptr); +} - // Process the shadow decls. - for (auto *Shadow : D->shadows()) { - // FIXME: UsingShadowDecl doesn't preserve its immediate target, so - // reconstruct it in the case where it matters. - NamedDecl *OldTarget = Shadow->getTargetDecl(); - if (auto *CUSD = dyn_cast<ConstructorUsingShadowDecl>(Shadow)) - if (auto *BaseShadow = CUSD->getNominatedBaseClassShadowDecl()) - OldTarget = BaseShadow; +Decl *TemplateDeclInstantiator::VisitUsingEnumDecl(UsingEnumDecl *D) { + // Cannot be a dependent type, but still could be an instantiation + EnumDecl *EnumD = cast_or_null<EnumDecl>(SemaRef.FindInstantiatedDecl( + D->getLocation(), D->getEnumDecl(), TemplateArgs)); - NamedDecl *InstTarget = - cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), OldTarget, TemplateArgs)); - if (!InstTarget) - return nullptr; + if (SemaRef.RequireCompleteEnumDecl(EnumD, EnumD->getLocation())) + return nullptr; - UsingShadowDecl *PrevDecl = nullptr; - if (CheckRedeclaration) { - if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl)) - continue; - } else if (UsingShadowDecl *OldPrev = - getPreviousDeclForInstantiation(Shadow)) { - PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), OldPrev, TemplateArgs)); - } + TypeSourceInfo *TSI = SemaRef.SubstType(D->getEnumType(), TemplateArgs, + D->getLocation(), D->getDeclName()); + UsingEnumDecl *NewUD = + UsingEnumDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(), + D->getEnumLoc(), D->getLocation(), TSI); - UsingShadowDecl *InstShadow = - SemaRef.BuildUsingShadowDecl(/*Scope*/nullptr, NewUD, InstTarget, - PrevDecl); - SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); + SemaRef.Context.setInstantiatedFromUsingEnumDecl(NewUD, D); + NewUD->setAccess(D->getAccess()); + Owner->addDecl(NewUD); - if (isFunctionScope) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); - } + // Don't process the shadow decls for an invalid decl. + if (NewUD->isInvalidDecl()) + return NewUD; + + // We don't have to recheck for duplication of the UsingEnumDecl itself, as it + // cannot be dependent, and will therefore have been checked during template + // definition. - return NewUD; + return VisitBaseUsingDecls(D, NewUD, nullptr); } Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) { @@ -3141,7 +3417,7 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( // be expanded. bool Expand = true; bool RetainExpansion = false; - Optional<unsigned> NumExpansions; + std::optional<unsigned> NumExpansions; if (SemaRef.CheckParameterPacksForExpansion( D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, TemplateArgs, Expand, RetainExpansion, NumExpansions)) @@ -3214,13 +3490,16 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( SourceLocation EllipsisLoc = InstantiatingSlice ? SourceLocation() : D->getEllipsisLoc(); + bool IsUsingIfExists = D->template hasAttr<UsingIfExistsAttr>(); NamedDecl *UD = SemaRef.BuildUsingDeclaration( /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, ParsedAttributesView(), - /*IsInstantiation*/ true); - if (UD) + /*IsInstantiation*/ true, IsUsingIfExists); + if (UD) { + SemaRef.InstantiateAttrs(TemplateArgs, D, UD); SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); + } return UD; } @@ -3235,6 +3514,11 @@ Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl( return instantiateUnresolvedUsingDecl(D); } +Decl *TemplateDeclInstantiator::VisitUnresolvedUsingIfExistsDecl( + UnresolvedUsingIfExistsDecl *D) { + llvm_unreachable("referring to unresolved decl out of UsingShadowDecl"); +} + Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { SmallVector<NamedDecl*, 8> Expansions; for (auto *UD : D->expansions()) { @@ -3251,13 +3535,6 @@ Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { return NewD; } -Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *Decl) { - CXXMethodDecl *OldFD = Decl->getSpecialization(); - return cast_or_null<CXXMethodDecl>( - VisitCXXMethodDecl(OldFD, nullptr, Decl->getTemplateArgsAsWritten())); -} - Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( OMPThreadPrivateDecl *D) { SmallVector<Expr *, 5> Vars; @@ -3286,12 +3563,23 @@ Decl *TemplateDeclInstantiator::VisitOMPAllocateDecl(OMPAllocateDecl *D) { SmallVector<OMPClause *, 4> Clauses; // Copy map clauses from the original mapper. for (OMPClause *C : D->clauselists()) { - auto *AC = cast<OMPAllocatorClause>(C); - ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs); - if (!NewE.isUsable()) - continue; - OMPClause *IC = SemaRef.ActOnOpenMPAllocatorClause( - NewE.get(), AC->getBeginLoc(), AC->getLParenLoc(), AC->getEndLoc()); + OMPClause *IC = nullptr; + if (auto *AC = dyn_cast<OMPAllocatorClause>(C)) { + ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs); + if (!NewE.isUsable()) + continue; + IC = SemaRef.ActOnOpenMPAllocatorClause( + NewE.get(), AC->getBeginLoc(), AC->getLParenLoc(), AC->getEndLoc()); + } else if (auto *AC = dyn_cast<OMPAlignClause>(C)) { + ExprResult NewE = SemaRef.SubstExpr(AC->getAlignment(), TemplateArgs); + if (!NewE.isUsable()) + continue; + IC = SemaRef.ActOnOpenMPAlignClause(NewE.get(), AC->getBeginLoc(), + AC->getLParenLoc(), AC->getEndLoc()); + // If align clause value ends up being invalid, this can end up null. + if (!IC) + continue; + } Clauses.push_back(IC); } @@ -3370,7 +3658,7 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( SemaRef.CurrentInstantiationScope->InstantiatedLocal( cast<DeclRefExpr>(D->getInitPriv())->getDecl(), cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl()); - if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) { + if (D->getInitializerKind() == OMPDeclareReductionInitKind::Call) { SubstInitializer = SemaRef.SubstExpr(Init, TemplateArgs).get(); } else { auto *OldPrivParm = @@ -3385,9 +3673,9 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( } IsCorrect = IsCorrect && SubstCombiner && (!Init || - (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit && + (D->getInitializerKind() == OMPDeclareReductionInitKind::Call && SubstInitializer) || - (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit && + (D->getInitializerKind() != OMPDeclareReductionInitKind::Call && !SubstInitializer)); (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd( @@ -3461,9 +3749,10 @@ TemplateDeclInstantiator::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(), OldC->getEndLoc()); OMPClause *NewC = SemaRef.ActOnOpenMPMapClause( - OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS, - NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(), - OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs); + OldC->getIteratorModifier(), OldC->getMapTypeModifiers(), + OldC->getMapTypeModifiersLoc(), SS, NewNameInfo, OldC->getMapType(), + OldC->isImplicitMapType(), OldC->getMapLoc(), OldC->getColonLoc(), + NewVars, Locs); Clauses.push_back(NewC); } SemaRef.EndOpenMPDSABlock(nullptr); @@ -3530,26 +3819,23 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( SmallVector<TemplateArgumentLoc, 4> ArgLocs; for (unsigned I = 0; I != Loc.getNumArgs(); ++I) ArgLocs.push_back(Loc.getArgLoc(I)); - if (SemaRef.Subst(ArgLocs.data(), ArgLocs.size(), - InstTemplateArgs, TemplateArgs)) + if (SemaRef.SubstTemplateArguments(ArgLocs, TemplateArgs, InstTemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this // class template. - SmallVector<TemplateArgument, 4> Converted; - if (SemaRef.CheckTemplateArgumentList(InstClassTemplate, - D->getLocation(), - InstTemplateArgs, - false, - Converted, - /*UpdateArgsWithConversion=*/true)) + SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; + if (SemaRef.CheckTemplateArgumentList(InstClassTemplate, D->getLocation(), + InstTemplateArgs, false, + SugaredConverted, CanonicalConverted, + /*UpdateArgsWithConversions=*/true)) return nullptr; // Figure out where to insert this class template explicit specialization // in the member template's set of class template explicit specializations. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = - InstClassTemplate->findSpecialization(Converted, InsertPos); + InstClassTemplate->findSpecialization(CanonicalConverted, InsertPos); // Check whether we've already seen a conflicting instantiation of this // declaration (for instance, if there was a prior implicit instantiation). @@ -3587,7 +3873,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *InstD = ClassTemplateSpecializationDecl::Create( SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), - D->getLocation(), InstClassTemplate, Converted, PrevDecl); + D->getLocation(), InstClassTemplate, CanonicalConverted, PrevDecl); // Add this partial specialization to the set of class template partial // specializations. @@ -3601,7 +3887,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( // Build the canonical type that describes the converted template // arguments of the class template explicit specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType( - TemplateName(InstClassTemplate), Converted, + TemplateName(InstClassTemplate), CanonicalConverted, SemaRef.Context.getRecordType(InstD)); // Build the fully-sugared type for this class template @@ -3652,25 +3938,28 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( return nullptr; // Substitute the current template arguments. - const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo(); - VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc()); - VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc()); + if (const ASTTemplateArgumentListInfo *TemplateArgsInfo = + D->getTemplateArgsInfo()) { + VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo->getLAngleLoc()); + VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo->getRAngleLoc()); - if (SemaRef.Subst(TemplateArgsInfo.getArgumentArray(), - TemplateArgsInfo.size(), VarTemplateArgsInfo, TemplateArgs)) - return nullptr; + if (SemaRef.SubstTemplateArguments(TemplateArgsInfo->arguments(), + TemplateArgs, VarTemplateArgsInfo)) + return nullptr; + } // Check that the template argument list is well-formed for this template. - SmallVector<TemplateArgument, 4> Converted; + SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; if (SemaRef.CheckTemplateArgumentList(InstVarTemplate, D->getLocation(), - VarTemplateArgsInfo, false, Converted, - /*UpdateArgsWithConversion=*/true)) + VarTemplateArgsInfo, false, + SugaredConverted, CanonicalConverted, + /*UpdateArgsWithConversions=*/true)) return nullptr; // Check whether we've already seen a declaration of this specialization. void *InsertPos = nullptr; VarTemplateSpecializationDecl *PrevDecl = - InstVarTemplate->findSpecialization(Converted, InsertPos); + InstVarTemplate->findSpecialization(CanonicalConverted, InsertPos); // Check whether we've already seen a conflicting instantiation of this // declaration (for instance, if there was a prior implicit instantiation). @@ -3682,7 +3971,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( return nullptr; return VisitVarTemplateSpecializationDecl( - InstVarTemplate, D, VarTemplateArgsInfo, Converted, PrevDecl); + InstVarTemplate, D, VarTemplateArgsInfo, CanonicalConverted, PrevDecl); } Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( @@ -3747,6 +4036,11 @@ Decl *TemplateDeclInstantiator::VisitConceptDecl(ConceptDecl *D) { llvm_unreachable("Concept definitions cannot reside inside a template"); } +Decl *TemplateDeclInstantiator::VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D) { + llvm_unreachable("Concept specializations cannot reside inside a template"); +} + Decl * TemplateDeclInstantiator::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { return RequiresExprBodyDecl::Create(SemaRef.Context, D->getDeclContext(), @@ -3818,14 +4112,14 @@ FunctionDecl *Sema::SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD, Decl *R; if (auto *MD = dyn_cast<CXXMethodDecl>(Spaceship)) { R = Instantiator.VisitCXXMethodDecl( - MD, nullptr, None, + MD, /*TemplateParams=*/nullptr, TemplateDeclInstantiator::RewriteKind::RewriteSpaceshipAsEqualEqual); } else { assert(Spaceship->getFriendObjectKind() && "defaulted spaceship is neither a member nor a friend"); R = Instantiator.VisitFunctionDecl( - Spaceship, nullptr, + Spaceship, /*TemplateParams=*/nullptr, TemplateDeclInstantiator::RewriteKind::RewriteSpaceshipAsEqualEqual); if (!R) return nullptr; @@ -3864,18 +4158,7 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { if (Invalid) return nullptr; - // FIXME: Concepts: Substitution into requires clause should only happen when - // checking satisfaction. - Expr *InstRequiresClause = nullptr; - if (Expr *E = L->getRequiresClause()) { - EnterExpressionEvaluationContext ConstantEvaluated( - SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); - ExprResult Res = SemaRef.SubstExpr(E, TemplateArgs); - if (Res.isInvalid() || !Res.isUsable()) { - return nullptr; - } - InstRequiresClause = Res.get(); - } + Expr *InstRequiresClause = L->getRequiresClause(); TemplateParameterList *InstL = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(), @@ -3886,8 +4169,10 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { TemplateParameterList * Sema::SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EvaluateConstraints) { TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); + Instantiator.setEvaluateConstraints(EvaluateConstraints); return Instantiator.SubstTemplateParams(Params); } @@ -3924,39 +4209,35 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( = PartialSpec->getTemplateArgsAsWritten(); TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, TemplArgInfo->RAngleLoc); - if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), - TemplArgInfo->NumTemplateArgs, - InstTemplateArgs, TemplateArgs)) + if (SemaRef.SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs, + InstTemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this // class template. - SmallVector<TemplateArgument, 4> Converted; - if (SemaRef.CheckTemplateArgumentList(ClassTemplate, - PartialSpec->getLocation(), - InstTemplateArgs, - false, - Converted)) + SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; + if (SemaRef.CheckTemplateArgumentList( + ClassTemplate, PartialSpec->getLocation(), InstTemplateArgs, + /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted)) return nullptr; // Check these arguments are valid for a template partial specialization. if (SemaRef.CheckTemplatePartialSpecializationArgs( PartialSpec->getLocation(), ClassTemplate, InstTemplateArgs.size(), - Converted)) + CanonicalConverted)) return nullptr; // Figure out where to insert this class template partial specialization // in the member template's set of class template partial specializations. void *InsertPos = nullptr; - ClassTemplateSpecializationDecl *PrevDecl - = ClassTemplate->findPartialSpecialization(Converted, InstParams, + ClassTemplateSpecializationDecl *PrevDecl = + ClassTemplate->findPartialSpecialization(CanonicalConverted, InstParams, 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); + QualType CanonType = SemaRef.Context.getTemplateSpecializationType( + TemplateName(ClassTemplate), CanonicalConverted); // Build the fully-sugared type for this class template // specialization as the user wrote in the specialization @@ -4001,7 +4282,8 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( ClassTemplatePartialSpecializationDecl::Create( SemaRef.Context, PartialSpec->getTagKind(), Owner, PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, - ClassTemplate, Converted, InstTemplateArgs, CanonType, nullptr); + ClassTemplate, CanonicalConverted, InstTemplateArgs, CanonType, + nullptr); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return nullptr; @@ -4052,34 +4334,35 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( = PartialSpec->getTemplateArgsAsWritten(); TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, TemplArgInfo->RAngleLoc); - if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), - TemplArgInfo->NumTemplateArgs, - InstTemplateArgs, TemplateArgs)) + if (SemaRef.SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs, + InstTemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this // class template. - SmallVector<TemplateArgument, 4> Converted; - if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(), - InstTemplateArgs, false, Converted)) + SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; + if (SemaRef.CheckTemplateArgumentList( + VarTemplate, PartialSpec->getLocation(), InstTemplateArgs, + /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted)) return nullptr; // Check these arguments are valid for a template partial specialization. if (SemaRef.CheckTemplatePartialSpecializationArgs( PartialSpec->getLocation(), VarTemplate, InstTemplateArgs.size(), - Converted)) + CanonicalConverted)) return nullptr; // Figure out where to insert this variable template partial specialization // in the member template's set of variable template partial specializations. void *InsertPos = nullptr; VarTemplateSpecializationDecl *PrevDecl = - VarTemplate->findPartialSpecialization(Converted, InstParams, InsertPos); + VarTemplate->findPartialSpecialization(CanonicalConverted, InstParams, + InsertPos); // Build the canonical type that describes the converted template // arguments of the variable template partial specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType( - TemplateName(VarTemplate), Converted); + TemplateName(VarTemplate), CanonicalConverted); // Build the fully-sugared type for this variable template // specialization as the user wrote in the specialization @@ -4135,7 +4418,8 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( VarTemplatePartialSpecializationDecl::Create( SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), - DI, PartialSpec->getStorageClass(), Converted, InstTemplateArgs); + DI, PartialSpec->getStorageClass(), CanonicalConverted, + InstTemplateArgs); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) @@ -4168,14 +4452,12 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, Qualifiers ThisTypeQuals; if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { ThisContext = cast<CXXRecordDecl>(Owner); - ThisTypeQuals = Method->getMethodQualifiers(); + ThisTypeQuals = Method->getFunctionObjectParameterType().getQualifiers(); } - TypeSourceInfo *NewTInfo - = SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs, - D->getTypeSpecStartLoc(), - D->getDeclName(), - ThisContext, ThisTypeQuals); + TypeSourceInfo *NewTInfo = SemaRef.SubstFunctionDeclType( + OldTInfo, TemplateArgs, D->getTypeSpecStartLoc(), D->getDeclName(), + ThisContext, ThisTypeQuals, EvaluateConstraints); if (!NewTInfo) return nullptr; @@ -4194,7 +4476,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope; - Optional<unsigned> NumArgumentsInExpansion; + std::optional<unsigned> NumArgumentsInExpansion; if (OldParam->isParameterPack()) NumArgumentsInExpansion = SemaRef.getNumArgumentsInExpansion(OldParam->getType(), @@ -4259,13 +4541,43 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, return NewTInfo; } +/// Introduce the instantiated local variables into the local +/// instantiation scope. +void Sema::addInstantiatedLocalVarsToScope(FunctionDecl *Function, + const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope) { + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(getFunctionScopes().back()); + + for (auto *decl : PatternDecl->decls()) { + if (!isa<VarDecl>(decl) || isa<ParmVarDecl>(decl)) + continue; + + VarDecl *VD = cast<VarDecl>(decl); + IdentifierInfo *II = VD->getIdentifier(); + + auto it = llvm::find_if(Function->decls(), [&](Decl *inst) { + VarDecl *InstVD = dyn_cast<VarDecl>(inst); + return InstVD && InstVD->isLocalVarDecl() && + InstVD->getIdentifier() == II; + }); + + if (it == Function->decls().end()) + continue; + + Scope.InstantiatedLocal(VD, *it); + LSI->addCapture(cast<VarDecl>(*it), /*isBlock=*/false, /*isByref=*/false, + /*isNested=*/false, VD->getLocation(), SourceLocation(), + VD->getType(), /*Invalid=*/false); + } +} + /// Introduce the instantiated function parameters into the local /// instantiation scope, and set the parameter names to those used /// in the template. -static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, - const FunctionDecl *PatternDecl, - LocalInstantiationScope &Scope, - const MultiLevelTemplateArgumentList &TemplateArgs) { +bool Sema::addInstantiatedParametersToScope( + FunctionDecl *Function, const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope, + const MultiLevelTemplateArgumentList &TemplateArgs) { unsigned FParamIdx = 0; for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); @@ -4281,9 +4593,9 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, // it's instantiation-dependent. // FIXME: Updating the type to work around this is at best fragile. if (!PatternDecl->getType()->isDependentType()) { - QualType T = S.SubstType(PatternParam->getType(), TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); + QualType T = SubstType(PatternParam->getType(), TemplateArgs, + FunctionParam->getLocation(), + FunctionParam->getDeclName()); if (T.isNull()) return true; FunctionParam->setType(T); @@ -4296,8 +4608,8 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, // Expand the parameter pack. Scope.MakeInstantiatedLocalArgPack(PatternParam); - Optional<unsigned> NumArgumentsInExpansion - = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); + std::optional<unsigned> NumArgumentsInExpansion = + getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); if (NumArgumentsInExpansion) { QualType PatternType = PatternParam->getType()->castAs<PackExpansionType>()->getPattern(); @@ -4305,10 +4617,10 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); FunctionParam->setDeclName(PatternParam->getDeclName()); if (!PatternDecl->getType()->isDependentType()) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg); - QualType T = S.SubstType(PatternType, TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, Arg); + QualType T = + SubstType(PatternType, TemplateArgs, FunctionParam->getLocation(), + FunctionParam->getDeclName()); if (T.isNull()) return true; FunctionParam->setType(T); @@ -4326,10 +4638,6 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, ParmVarDecl *Param) { assert(Param->hasUninstantiatedDefaultArg()); - Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); - - EnterExpressionEvaluationContext EvalContext( - *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); // Instantiate the expression. // @@ -4348,63 +4656,13 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, // // template<typename T> // A<T> Foo(int a = A<T>::FooImpl()); - MultiLevelTemplateArgumentList TemplateArgs - = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true); - - InstantiatingTemplate Inst(*this, CallLoc, Param, - TemplateArgs.getInnermost()); - if (Inst.isInvalid()) - return true; - if (Inst.isAlreadyInstantiating()) { - Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD; - Param->setInvalidDecl(); - return true; - } + MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( + FD, FD->getLexicalDeclContext(), /*Final=*/false, nullptr, + /*RelativeToPrimary=*/true); - ExprResult Result; - { - // C++ [dcl.fct.default]p5: - // The names in the [default argument] expression are bound, and - // the semantic constraints are checked, at the point where the - // default argument expression appears. - ContextRAII SavedContext(*this, FD); - LocalInstantiationScope Local(*this); - - FunctionDecl *Pattern = FD->getTemplateInstantiationPattern( - /*ForDefinition*/ false); - if (addInstantiatedParametersToScope(*this, FD, Pattern, Local, - TemplateArgs)) - return true; - - runWithSufficientStackSpace(CallLoc, [&] { - Result = SubstInitializer(UninstExpr, TemplateArgs, - /*DirectInit*/false); - }); - } - if (Result.isInvalid()) - return true; - - // Check the expression as an initializer for the parameter. - InitializedEntity Entity - = InitializedEntity::InitializeParameter(Context, Param); - InitializationKind Kind = InitializationKind::CreateCopy( - Param->getLocation(), - /*FIXME:EqualLoc*/ UninstExpr->getBeginLoc()); - Expr *ResultE = Result.getAs<Expr>(); - - InitializationSequence InitSeq(*this, Entity, Kind, ResultE); - Result = InitSeq.Perform(*this, Entity, Kind, ResultE); - if (Result.isInvalid()) + if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true)) return true; - Result = - ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(), - /*DiscardedValue*/ false); - if (Result.isInvalid()) - return true; - - // Remember the instantiated default argument. - Param->setDefaultArg(Result.getAs<Expr>()); if (ASTMutationListener *L = getASTMutationListener()) L->DefaultArgumentInstantiated(Param); @@ -4438,16 +4696,16 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, Sema::ContextRAII savedContext(*this, Decl); LocalInstantiationScope Scope(*this); - MultiLevelTemplateArgumentList TemplateArgs = - getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true); + MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( + Decl, Decl->getLexicalDeclContext(), /*Final=*/false, nullptr, + /*RelativeToPrimary*/ true); // FIXME: We can't use getTemplateInstantiationPattern(false) in general // here, because for a non-defining friend declaration in a class template, // we don't store enough information to map back to the friend declaration in // the template. FunctionDecl *Template = Proto->getExceptionSpecTemplate(); - if (addInstantiatedParametersToScope(*this, Decl, Template, Scope, - TemplateArgs)) { + if (addInstantiatedParametersToScope(Decl, Template, Scope, TemplateArgs)) { UpdateExceptionSpec(Decl, EST_None); return; } @@ -4456,53 +4714,6 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, TemplateArgs); } -bool Sema::CheckInstantiatedFunctionTemplateConstraints( - SourceLocation PointOfInstantiation, FunctionDecl *Decl, - ArrayRef<TemplateArgument> TemplateArgs, - ConstraintSatisfaction &Satisfaction) { - // In most cases we're not going to have constraints, so check for that first. - FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); - // Note - code synthesis context for the constraints check is created - // inside CheckConstraintsSatisfaction. - SmallVector<const Expr *, 3> TemplateAC; - Template->getAssociatedConstraints(TemplateAC); - if (TemplateAC.empty()) { - Satisfaction.IsSatisfied = true; - return false; - } - - // Enter the scope of this instantiation. We don't use - // PushDeclContext because we don't have a scope. - Sema::ContextRAII savedContext(*this, Decl); - LocalInstantiationScope Scope(*this); - - // If this is not an explicit specialization - we need to get the instantiated - // version of the template arguments and add them to scope for the - // substitution. - if (Decl->isTemplateInstantiation()) { - InstantiatingTemplate Inst(*this, Decl->getPointOfInstantiation(), - InstantiatingTemplate::ConstraintsCheck{}, Decl->getPrimaryTemplate(), - TemplateArgs, SourceRange()); - if (Inst.isInvalid()) - return true; - MultiLevelTemplateArgumentList MLTAL( - *Decl->getTemplateSpecializationArgs()); - if (addInstantiatedParametersToScope( - *this, Decl, Decl->getPrimaryTemplate()->getTemplatedDecl(), - Scope, MLTAL)) - return true; - } - Qualifiers ThisQuals; - CXXRecordDecl *Record = nullptr; - if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { - ThisQuals = Method->getMethodQualifiers(); - Record = Method->getParent(); - } - CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); - return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs, - PointOfInstantiation, Satisfaction); -} - /// Initializes the common fields of an instantiation function /// declaration (New) from the corresponding fields of its template (Tmpl). /// @@ -4530,11 +4741,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back(); if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { - if (FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(ActiveInst.Entity)) { - assert(FunTmpl->getTemplatedDecl() == Tmpl && - "Deduction from the wrong function template?"); - (void) FunTmpl; + if (isa<FunctionTemplateDecl>(ActiveInst.Entity)) { SemaRef.InstantiatingSpecializations.erase( {ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind}); atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst); @@ -4661,7 +4868,8 @@ Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, return nullptr; ContextRAII SavedContext(*this, FD); - MultiLevelTemplateArgumentList MArgs(*Args); + MultiLevelTemplateArgumentList MArgs(FTD, Args->asArray(), + /*Final=*/false); return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs)); } @@ -4698,6 +4906,12 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (TSK == TSK_ExplicitSpecialization) return; + // Never implicitly instantiate a builtin; we don't actually need a function + // body. + if (Function->getBuiltinID() && TSK == TSK_ImplicitInstantiation && + !DefinitionRequired) + return; + // Don't instantiate a definition if we already have one. const FunctionDecl *ExistingDefn = nullptr; if (Function->isDefined(ExistingDefn, @@ -4733,7 +4947,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, /*Complain*/DefinitionRequired)) { if (DefinitionRequired) Function->setInvalidDecl(); - else if (TSK == TSK_ExplicitInstantiationDefinition) { + else if (TSK == TSK_ExplicitInstantiationDefinition || + (Function->isConstexpr() && !Recursive)) { // Try again at the end of the translation unit (at which point a // definition will be required). assert(!Recursive); @@ -4748,7 +4963,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); if (getLangOpts().CPlusPlus11) Diag(PointOfInstantiation, diag::note_inst_declaration_hint) - << Function; + << Function; } } @@ -4794,6 +5009,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, "missing LateParsedTemplate"); LateTemplateParser(OpaqueParser, *LPTIter->second); Pattern = PatternDecl->getBody(PatternDecl); + updateAttrsForLateParsedTemplate(PatternDecl, Function); } // Note, we should never try to instantiate a deleted function template. @@ -4832,8 +5048,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // unimported module. Function->setVisibleDespiteOwningModule(); - // Copy the inner loc start from the pattern. + // Copy the source locations from the pattern. + Function->setLocation(PatternDecl->getLocation()); Function->setInnerLocStart(PatternDecl->getInnerLocStart()); + Function->setRangeEnd(PatternDecl->getEndLoc()); EnterExpressionEvaluationContext EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); @@ -4850,12 +5068,80 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, Rec->isLocalClass() && !Function->isFunctionTemplateSpecialization(); LocalInstantiationScope Scope(*this, MergeWithParentScope); + auto RebuildTypeSourceInfoForDefaultSpecialMembers = [&]() { + // Special members might get their TypeSourceInfo set up w.r.t the + // PatternDecl context, in which case parameters could still be pointing + // back to the original class, make sure arguments are bound to the + // instantiated record instead. + assert(PatternDecl->isDefaulted() && + "Special member needs to be defaulted"); + auto PatternSM = getDefaultedFunctionKind(PatternDecl).asSpecialMember(); + if (!(PatternSM == Sema::CXXCopyConstructor || + PatternSM == Sema::CXXCopyAssignment || + PatternSM == Sema::CXXMoveConstructor || + PatternSM == Sema::CXXMoveAssignment)) + return; + + auto *NewRec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()); + const auto *PatternRec = + dyn_cast<CXXRecordDecl>(PatternDecl->getDeclContext()); + if (!NewRec || !PatternRec) + return; + if (!PatternRec->isLambda()) + return; - if (PatternDecl->isDefaulted()) + struct SpecialMemberTypeInfoRebuilder + : TreeTransform<SpecialMemberTypeInfoRebuilder> { + using Base = TreeTransform<SpecialMemberTypeInfoRebuilder>; + const CXXRecordDecl *OldDecl; + CXXRecordDecl *NewDecl; + + SpecialMemberTypeInfoRebuilder(Sema &SemaRef, const CXXRecordDecl *O, + CXXRecordDecl *N) + : TreeTransform(SemaRef), OldDecl(O), NewDecl(N) {} + + bool TransformExceptionSpec(SourceLocation Loc, + FunctionProtoType::ExceptionSpecInfo &ESI, + SmallVectorImpl<QualType> &Exceptions, + bool &Changed) { + return false; + } + + QualType TransformRecordType(TypeLocBuilder &TLB, RecordTypeLoc TL) { + const RecordType *T = TL.getTypePtr(); + RecordDecl *Record = cast_or_null<RecordDecl>( + getDerived().TransformDecl(TL.getNameLoc(), T->getDecl())); + if (Record != OldDecl) + return Base::TransformRecordType(TLB, TL); + + QualType Result = getDerived().RebuildRecordType(NewDecl); + if (Result.isNull()) + return QualType(); + + RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } + } IR{*this, PatternRec, NewRec}; + + TypeSourceInfo *NewSI = IR.TransformType(Function->getTypeSourceInfo()); + assert(NewSI && "Type Transform failed?"); + Function->setType(NewSI->getType()); + Function->setTypeSourceInfo(NewSI); + + ParmVarDecl *Parm = Function->getParamDecl(0); + TypeSourceInfo *NewParmSI = IR.TransformType(Parm->getTypeSourceInfo()); + Parm->setType(NewParmSI->getType()); + Parm->setTypeSourceInfo(NewParmSI); + }; + + if (PatternDecl->isDefaulted()) { + RebuildTypeSourceInfoForDefaultSpecialMembers(); SetDeclDefaulted(Function, PatternDecl->getLocation()); - else { - MultiLevelTemplateArgumentList TemplateArgs = - getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl); + } else { + MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( + Function, Function->getLexicalDeclContext(), /*Final=*/false, nullptr, + false, PatternDecl); // Substitute into the qualifier; we can get a substitution failure here // through evil use of alias templates. @@ -4869,7 +5155,11 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // PushDeclContext because we don't have a scope. Sema::ContextRAII savedContext(*this, Function); - if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope, + FPFeaturesStateRAII SavedFPFeatures(*this); + CurFPFeatures = FPOptions(getLangOpts()); + FpPragmaStack.CurrentValue = FPOptionsOverride(); + + if (addInstantiatedParametersToScope(Function, PatternDecl, Scope, TemplateArgs)) return; @@ -4924,8 +5214,7 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( const TemplateArgumentList &TemplateArgList, const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl<TemplateArgument> &Converted, - SourceLocation PointOfInstantiation, - LateInstantiatedAttrVec *LateAttrs, + SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *StartingScope) { if (FromVar->isInvalidDecl()) return nullptr; @@ -4934,9 +5223,6 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( if (Inst.isInvalid()) return nullptr; - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgList); - // Instantiate the first declaration of the variable template: for a partial // specialization of a static data member template, the first declaration may // or may not be the declaration in the class; if it's in the class, we want @@ -4947,15 +5233,21 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( // partial specialization, don't do this. The member specialization completely // replaces the original declaration in this case. bool IsMemberSpec = false; - if (VarTemplatePartialSpecializationDecl *PartialSpec = - dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar)) + MultiLevelTemplateArgumentList MultiLevelList; + if (auto *PartialSpec = + dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar)) { IsMemberSpec = PartialSpec->isMemberSpecialization(); - else if (VarTemplateDecl *FromTemplate = FromVar->getDescribedVarTemplate()) - IsMemberSpec = FromTemplate->isMemberSpecialization(); + MultiLevelList.addOuterTemplateArguments( + PartialSpec, TemplateArgList.asArray(), /*Final=*/false); + } else { + assert(VarTemplate == FromVar->getDescribedVarTemplate()); + IsMemberSpec = VarTemplate->isMemberSpecialization(); + MultiLevelList.addOuterTemplateArguments( + VarTemplate, TemplateArgList.asArray(), /*Final=*/false); + } if (!IsMemberSpec) FromVar = FromVar->getFirstDecl(); - MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList); TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(), MultiLevelList); @@ -5033,7 +5325,6 @@ void Sema::BuildVariableInstantiation( NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl()); NewVar->setObjCForDecl(OldVar->isObjCForDecl()); NewVar->setConstexpr(OldVar->isConstexpr()); - MaybeAddCUDAConstantAttr(NewVar); NewVar->setInitCapture(OldVar->isInitCapture()); NewVar->setPreviousDeclInSameBlockScope( OldVar->isPreviousDeclInSameBlockScope()); @@ -5385,8 +5676,18 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // declaration of the definition. TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(), TemplateArgs); + + TemplateArgumentListInfo TemplateArgInfo; + if (const ASTTemplateArgumentListInfo *ArgInfo = + VarSpec->getTemplateArgsInfo()) { + TemplateArgInfo.setLAngleLoc(ArgInfo->getLAngleLoc()); + TemplateArgInfo.setRAngleLoc(ArgInfo->getRAngleLoc()); + for (const TemplateArgumentLoc &Arg : ArgInfo->arguments()) + TemplateArgInfo.addArgument(Arg); + } + Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl( - VarSpec->getSpecializedTemplate(), Def, VarSpec->getTemplateArgsInfo(), + VarSpec->getSpecializedTemplate(), Def, TemplateArgInfo, VarSpec->getTemplateArgs().asArray(), VarSpec)); if (Var) { llvm::PointerUnion<VarTemplateDecl *, @@ -5445,7 +5746,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, collectUnexpandedParameterPacks(Init->getInit(), Unexpanded); bool ShouldExpand = false; bool RetainExpansion = false; - Optional<unsigned> NumExpansions; + std::optional<unsigned> NumExpansions; if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), BaseTL.getSourceRange(), Unexpanded, @@ -5826,11 +6127,11 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, bool FindingInstantiatedContext) { DeclContext *ParentDC = D->getDeclContext(); - // Determine whether our parent context depends on any of the tempalte + // Determine whether our parent context depends on any of the template // arguments we're currently substituting. bool ParentDependsOnArgs = isDependentContextAtLevel( ParentDC, TemplateArgs.getNumRetainedOuterLevels()); - // FIXME: Parmeters of pointer to functions (y below) that are themselves + // FIXME: Parameters of pointer to functions (y below) that are themselves // parameters (p below) can have their ParentDC set to the translation-unit // - thus we can not consistently check if the ParentDC of such a parameter // is Dependent or/and a FunctionOrMethod. @@ -5854,7 +6155,9 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, (ParentDependsOnArgs && (ParentDC->isFunctionOrMethod() || isa<OMPDeclareReductionDecl>(ParentDC) || isa<OMPDeclareMapperDecl>(ParentDC))) || - (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) { + (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda() && + cast<CXXRecordDecl>(D)->getTemplateDepth() > + TemplateArgs.getNumRetainedOuterLevels())) { // D is a local of some kind. Look into the map of local // declarations to their instantiations. if (CurrentInstantiationScope) { @@ -5923,13 +6226,13 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, return D; // Determine whether this record is the "templated" declaration describing - // a class template or class template partial specialization. + // a class template or class template specialization. ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); if (ClassTemplate) ClassTemplate = ClassTemplate->getCanonicalDecl(); - else if (ClassTemplatePartialSpecializationDecl *PartialSpec - = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) - ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl(); + else if (ClassTemplateSpecializationDecl *Spec = + dyn_cast<ClassTemplateSpecializationDecl>(Record)) + ClassTemplate = Spec->getSpecializedTemplate()->getCanonicalDecl(); // Walk the current context to find either the record or an instantiation of // it. @@ -5957,7 +6260,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // Move to the outer template scope. if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) { - if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){ + if (FD->getFriendObjectKind() && + FD->getNonTransparentDeclContext()->isFileContext()) { DC = FD->getLexicalDeclContext(); continue; } @@ -6198,7 +6502,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) { - for (auto DD : Pattern->ddiags()) { + for (auto *DD : Pattern->ddiags()) { switch (DD->getKind()) { case DependentDiagnostic::Access: HandleDependentAccessCheck(*DD, TemplateArgs); |