aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp346
1 files changed, 254 insertions, 92 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index dc1e0ef60cac..be4c51930789 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/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"
@@ -23,6 +24,7 @@
#include "clang/Basic/TargetInfo.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"
@@ -474,7 +476,7 @@ static void instantiateOMPDeclareVariantAttr(
SourceLocation(), SubstFD,
/* RefersToEnclosingVariableOrCapture */ false,
/* NameLoc */ SubstFD->getLocation(),
- SubstFD->getType(), ExprValueKind::VK_RValue);
+ SubstFD->getType(), ExprValueKind::VK_PRValue);
}
}
}
@@ -548,6 +550,35 @@ static void instantiateDependentAMDGPUWavesPerEUAttr(
S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr);
}
+// 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) {
+ // Functions cannot be partially specialized, so if we are being instantiated,
+ // we are obviously a complete specialization. Since this attribute is only
+ // valid on function template declarations, we know that this is a full
+ // instantiation of a kernel.
+ S.AddSYCLKernelLambda(cast<FunctionDecl>(New));
+
+ // Evaluate whether this would change any of the already evaluated
+ // __builtin_sycl_unique_stable_name values.
+ for (auto &Itr : S.Context.SYCLUniqueStableNameEvaluatedValues) {
+ const std::string &CurName = Itr.first->ComputeName(S.Context);
+ if (Itr.second != CurName) {
+ S.Diag(New->getLocation(),
+ diag::err_kernel_invalidates_sycl_unique_stable_name);
+ S.Diag(Itr.first->getLocation(),
+ diag::note_sycl_unique_stable_name_evaluated_here);
+ // Update this so future diagnostics work correctly.
+ Itr.second = CurName;
+ }
+ }
+
+ New->addAttr(Attr.clone(S.getASTContext()));
+}
+
/// Determine whether the attribute A might be relevent to the declaration D.
/// If not, we can skip instantiating it. The attribute may or may not have
/// been instantiated yet.
@@ -723,6 +754,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
@@ -856,10 +892,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()) &&
@@ -1050,11 +1087,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);
+ 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());
@@ -1517,48 +1573,18 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
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;
- }
+ if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, true,
+ Sema::TPL_TemplateMatch))
+ return nullptr;
// Do some additional validation, then merge default arguments
// from the existing declarations.
- if (!AdoptedPreviousTemplateParams &&
- SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
+ if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
Sema::TPC_ClassTemplate))
return nullptr;
}
@@ -1800,9 +1826,16 @@ 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;
+ if (D->isLambda())
+ Record = CXXRecordDecl::CreateLambda(
+ SemaRef.Context, Owner, D->getLambdaTypeInfo(), D->getLocation(),
+ D->isDependentLambda(), D->isGenericLambda(),
+ D->getLambdaCaptureDefault());
+ else
+ Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
+ D->getBeginLoc(), D->getLocation(),
+ D->getIdentifier(), PrevDecl);
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Record))
@@ -2281,6 +2314,20 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
if (InstantiatedExplicitSpecifier.isInvalid())
return nullptr;
+ // 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);
if (!TInfo)
@@ -2370,6 +2417,9 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
Destructor->isInlineSpecified(), false, Destructor->getConstexprKind(),
TrailingRequiresClause);
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,
@@ -2610,7 +2660,6 @@ Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
TemplateTypeParmDecl *D) {
- // TODO: don't always clone when decls are refcounted.
assert(D->getTypeForDecl()->isTemplateTypeParmType());
Optional<unsigned> NumExpanded;
@@ -3009,6 +3058,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 +3130,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 +3153,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 +3168,39 @@ 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));
- }
+ UsingEnumDecl *NewUD =
+ UsingEnumDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(),
+ D->getEnumLoc(), D->getLocation(), EnumD);
- 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;
- 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 VisitBaseUsingDecls(D, NewUD, nullptr);
}
Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
@@ -3214,13 +3300,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 +3324,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()) {
@@ -4841,16 +4935,85 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// Introduce a new scope where local variable instantiations will be
// recorded, unless we're actually a member function within a local
// class, in which case we need to merge our results with the parent
- // scope (of the enclosing function).
+ // scope (of the enclosing function). The exception is instantiating
+ // a function template specialization, since the template to be
+ // instantiated already has references to locals properly substituted.
bool MergeWithParentScope = false;
if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
- MergeWithParentScope = Rec->isLocalClass();
+ MergeWithParentScope =
+ 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;
+
+ struct SpecialMemberTypeInfoRebuilder
+ : TreeTransform<SpecialMemberTypeInfoRebuilder> {
+ using Base = TreeTransform<SpecialMemberTypeInfoRebuilder>;
+ const CXXRecordDecl *OldDecl;
+ CXXRecordDecl *NewDecl;
- if (PatternDecl->isDefaulted())
+ 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());
+ 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 {
+ } else {
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
@@ -5030,7 +5193,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());