aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp1422
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);