-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang] fix transformation of subst constant template parameter nodes #161029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang-modules Author: Matheus Izvekov (mizvekov) ChangesThis simplifies those transforms a lot, removing a bunch of workarounds which were introducing problems. The transforms become independent of the template instantiator, so they are moved to TreeTransform instead. Fixes #131342 This PR was already reviewed and approved at #160777, but I accidentally merged that into another PR, instead of main. Patch is 28.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/161029.diff 13 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6cfe42b5dc9f8..98c889c08b329 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -361,6 +361,7 @@ Bug Fixes in This Version
first parameter. (#GH113323).
- Fixed a crash with incompatible pointer to integer conversions in designated
initializers involving string literals. (#GH154046)
+- Fix crash on CTAD for alias template. (#GH131342)
- Clang now emits a frontend error when a function marked with the `flatten` attribute
calls another function that requires target features not enabled in the caller. This
prevents a fatal error in the backend.
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 9fedb230ce397..5f16bac94d5e6 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -4714,7 +4714,7 @@ class SubstNonTypeTemplateParmExpr : public Expr {
// sugared: it doesn't need to be resugared later.
bool getFinal() const { return Final; }
- NamedDecl *getParameter() const;
+ NonTypeTemplateParmDecl *getParameter() const;
bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); }
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index b02d9c7499fe5..e0d00b82f2b76 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -3495,7 +3495,9 @@ class AdjustedType : public Type, public llvm::FoldingSetNode {
AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy,
QualType CanonicalPtr)
- : Type(TC, CanonicalPtr, OriginalTy->getDependence()),
+ : Type(TC, CanonicalPtr,
+ AdjustedTy->getDependence() |
+ (OriginalTy->getDependence() & ~TypeDependence::Dependent)),
OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {}
public:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5edfc29d93781..2bd6be2a32cd5 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11714,6 +11714,23 @@ class Sema final : public SemaBase {
const TemplateArgumentListInfo *TemplateArgs,
bool IsAddressOfOperand);
+ UnsignedOrNone getPackIndex(TemplateArgument Pack) const {
+ return Pack.pack_size() - 1 - *ArgPackSubstIndex;
+ }
+
+ TemplateArgument
+ getPackSubstitutedTemplateArgument(TemplateArgument Arg) const {
+ Arg = Arg.pack_elements()[*ArgPackSubstIndex];
+ if (Arg.isPackExpansion())
+ Arg = Arg.getPackExpansionPattern();
+ return Arg;
+ }
+
+ ExprResult BuildSubstNonTypeTemplateParmExpr(
+ Decl *AssociatedDecl, const NonTypeTemplateParmDecl *NTTP,
+ SourceLocation loc, TemplateArgument Replacement,
+ UnsignedOrNone PackIndex, bool Final);
+
/// Form a template name from a name that is syntactically required to name a
/// template, either due to use of the 'template' keyword or because a name in
/// this syntactic context is assumed to name a template (C++
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 97ae4a07f32aa..95de6a82a5270 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1725,8 +1725,8 @@ SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs);
}
-NamedDecl *SubstNonTypeTemplateParmExpr::getParameter() const {
- return cast<NamedDecl>(
+NonTypeTemplateParmDecl *SubstNonTypeTemplateParmExpr::getParameter() const {
+ return cast<NonTypeTemplateParmDecl>(
getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]);
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 37c4d43ec0b2f..8b3af94e1a8bc 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1353,7 +1353,8 @@ void StmtProfiler::VisitExpr(const Expr *S) {
}
void StmtProfiler::VisitConstantExpr(const ConstantExpr *S) {
- VisitExpr(S);
+ // Profile exactly as the sub-expression.
+ Visit(S->getSubExpr());
}
void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 91e4dc8a2d039..3ebbb30ae483e 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -775,6 +775,40 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
TemplateArgs);
}
+ExprResult Sema::BuildSubstNonTypeTemplateParmExpr(
+ Decl *AssociatedDecl, const NonTypeTemplateParmDecl *NTTP,
+ SourceLocation Loc, TemplateArgument Arg, UnsignedOrNone PackIndex,
+ bool Final) {
+ // The template argument itself might be an expression, in which case we just
+ // return that expression. This happens when substituting into an alias
+ // template.
+ Expr *Replacement;
+ bool refParam = true;
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ Replacement = Arg.getAsExpr();
+ refParam = Replacement->isLValue();
+ if (refParam && Replacement->getType()->isRecordType()) {
+ QualType ParamType =
+ NTTP->isExpandedParameterPack()
+ ? NTTP->getExpansionType(*SemaRef.ArgPackSubstIndex)
+ : NTTP->getType();
+ if (const auto *PET = dyn_cast<PackExpansionType>(ParamType))
+ ParamType = PET->getPattern();
+ refParam = ParamType->isReferenceType();
+ }
+ } else {
+ ExprResult result =
+ SemaRef.BuildExpressionFromNonTypeTemplateArgument(Arg, Loc);
+ if (result.isInvalid())
+ return ExprError();
+ Replacement = result.get();
+ refParam = Arg.getNonTypeTemplateArgumentType()->isReferenceType();
+ }
+ return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
+ Replacement->getType(), Replacement->getValueKind(), Loc, Replacement,
+ AssociatedDecl, NTTP->getIndex(), PackIndex, refParam, Final);
+}
+
bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
NamedDecl *Instantiation,
bool InstantiatedFromMember,
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a72c95d6d77cf..1ff94d7ae397f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1373,16 +1373,6 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
return std::nullopt;
}
-static TemplateArgument
-getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
- assert(S.ArgPackSubstIndex);
- assert(*S.ArgPackSubstIndex < Arg.pack_size());
- Arg = Arg.pack_begin()[*S.ArgPackSubstIndex];
- if (Arg.isPackExpansion())
- Arg = Arg.getPackExpansionPattern();
- return Arg;
-}
-
//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
@@ -1449,13 +1439,6 @@ namespace {
return TemplateArgs.getNewDepth(Depth);
}
- UnsignedOrNone getPackIndex(TemplateArgument Pack) {
- UnsignedOrNone Index = getSema().ArgPackSubstIndex;
- if (!Index)
- return std::nullopt;
- return Pack.pack_size() - 1 - *Index;
- }
-
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
@@ -1537,7 +1520,7 @@ namespace {
if (TA.getKind() != TemplateArgument::Pack)
return TA;
if (SemaRef.ArgPackSubstIndex)
- return getPackSubstitutedTemplateArgument(SemaRef, TA);
+ return SemaRef.getPackSubstitutedTemplateArgument(TA);
assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
"unexpected pack arguments in template rewrite");
TemplateArgument Arg = *TA.pack_begin();
@@ -1643,10 +1626,6 @@ namespace {
ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *D);
- ExprResult TransformSubstNonTypeTemplateParmPackExpr(
- SubstNonTypeTemplateParmPackExpr *E);
- ExprResult TransformSubstNonTypeTemplateParmExpr(
- SubstNonTypeTemplateParmExpr *E);
/// Rebuild a DeclRefExpr for a VarDecl reference.
ExprResult RebuildVarDeclRefExpr(ValueDecl *PD, SourceLocation Loc);
@@ -1933,12 +1912,6 @@ namespace {
SmallVectorImpl<QualType> &PTypes,
SmallVectorImpl<ParmVarDecl *> &TransParams,
Sema::ExtParameterInfoBuilder &PInfos);
-
- private:
- ExprResult
- transformNonTypeTemplateParmRef(Decl *AssociatedDecl, const NamedDecl *parm,
- SourceLocation loc, TemplateArgument arg,
- UnsignedOrNone PackIndex, bool Final);
};
}
@@ -1975,7 +1948,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
TemplateName Template = Arg.getAsTemplate();
@@ -2079,7 +2052,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
if (!getSema().ArgPackSubstIndex)
return nullptr;
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
QualType T = Arg.getAsType();
@@ -2165,8 +2138,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
Arg, AssociatedDecl, TTP->getIndex(), Final);
}
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
TemplateName Template = Arg.getAsTemplate();
@@ -2183,10 +2156,10 @@ TemplateName TemplateInstantiator::TransformTemplateName(
TemplateArgument Pack = SubstPack->getArgumentPack();
TemplateName Template =
- getPackSubstitutedTemplateArgument(getSema(), Pack).getAsTemplate();
+ SemaRef.getPackSubstitutedTemplateArgument(Pack).getAsTemplate();
return getSema().Context.getSubstTemplateTemplateParm(
Template, SubstPack->getAssociatedDecl(), SubstPack->getIndex(),
- getPackIndex(Pack), SubstPack->getFinal());
+ SemaRef.getPackIndex(Pack), SubstPack->getFinal());
}
return inherited::TransformTemplateName(
@@ -2252,11 +2225,11 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition(), Final);
}
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
- return transformNonTypeTemplateParmRef(AssociatedDecl, NTTP, E->getLocation(),
- Arg, PackIndex, Final);
+ return SemaRef.BuildSubstNonTypeTemplateParmExpr(
+ AssociatedDecl, NTTP, E->getLocation(), Arg, PackIndex, Final);
}
const AnnotateAttr *
@@ -2344,144 +2317,6 @@ TemplateInstantiator::TransformOpenACCRoutineDeclAttr(
"applies to a Function Decl (and a few places for VarDecl)");
}
-ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
- Decl *AssociatedDecl, const NamedDecl *parm, SourceLocation loc,
- TemplateArgument arg, UnsignedOrNone PackIndex, bool Final) {
- ExprResult result;
-
- // Determine the substituted parameter type. We can usually infer this from
- // the template argument, but not always.
- auto SubstParamType = [&] {
- if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(parm)) {
- QualType T;
- if (NTTP->isExpandedParameterPack())
- T = NTTP->getExpansionType(*SemaRef.ArgPackSubstIndex);
- else
- T = NTTP->getType();
- if (parm->isParameterPack() && isa<PackExpansionType>(T))
- T = cast<PackExpansionType>(T)->getPattern();
- return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName());
- }
- return SemaRef.SubstType(arg.getAsExpr()->getType(), TemplateArgs, loc,
- parm->getDeclName());
- };
-
- bool refParam = false;
-
- // The template argument itself might be an expression, in which case we just
- // return that expression. This happens when substituting into an alias
- // template.
- if (arg.getKind() == TemplateArgument::Expression) {
- Expr *argExpr = arg.getAsExpr();
- result = argExpr;
- if (argExpr->isLValue()) {
- if (argExpr->getType()->isRecordType()) {
- // Check whether the parameter was actually a reference.
- QualType paramType = SubstParamType();
- if (paramType.isNull())
- return ExprError();
- refParam = paramType->isReferenceType();
- } else {
- refParam = true;
- }
- }
- } else if (arg.getKind() == TemplateArgument::Declaration ||
- arg.getKind() == TemplateArgument::NullPtr) {
- if (arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = arg.getAsDecl();
-
- // Find the instantiation of the template argument. This is
- // required for nested templates.
- VD = cast_or_null<ValueDecl>(
- getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
- if (!VD)
- return ExprError();
- }
-
- QualType paramType = arg.getNonTypeTemplateArgumentType();
- assert(!paramType.isNull() && "type substitution failed for param type");
- assert(!paramType->isDependentType() && "param type still dependent");
- result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
- refParam = paramType->isReferenceType();
- } else {
- QualType paramType = arg.getNonTypeTemplateArgumentType();
- result = SemaRef.BuildExpressionFromNonTypeTemplateArgument(arg, loc);
- refParam = paramType->isReferenceType();
- assert(result.isInvalid() ||
- SemaRef.Context.hasSameType(result.get()->getType(),
- paramType.getNonReferenceType()));
- }
-
- if (result.isInvalid())
- return ExprError();
-
- Expr *resultExpr = result.get();
- return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
- resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr,
- AssociatedDecl,
- clang::getDepthAndIndex(const_cast<NamedDecl *>(parm)).second, PackIndex,
- refParam, Final);
-}
-
-ExprResult
-TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
- SubstNonTypeTemplateParmPackExpr *E) {
- if (!getSema().ArgPackSubstIndex) {
- // We aren't expanding the parameter pack, so just return ourselves.
- return E;
- }
-
- TemplateArgument Pack = E->getArgumentPack();
- TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
- return transformNonTypeTemplateParmRef(
- E->getAssociatedDecl(), E->getParameterPack(),
- E->getParameterPackLocation(), Arg, getPackIndex(Pack), E->getFinal());
-}
-
-ExprResult
-TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
- SubstNonTypeTemplateParmExpr *E) {
- ExprResult SubstReplacement = E->getReplacement();
- if (!isa<ConstantExpr>(SubstReplacement.get()))
- SubstReplacement = TransformExpr(E->getReplacement());
- if (SubstReplacement.isInvalid())
- return true;
- QualType SubstType = TransformType(E->getParameterType(getSema().Context));
- if (SubstType.isNull())
- return true;
- // The type may have been previously dependent and not now, which means we
- // might have to implicit cast the argument to the new type, for example:
- // template<auto T, decltype(T) U>
- // concept C = sizeof(U) == 4;
- // void foo() requires C<2, 'a'> { }
- // When normalizing foo(), we first form the normalized constraints of C:
- // AtomicExpr(sizeof(U) == 4,
- // U=SubstNonTypeTemplateParmExpr(Param=U,
- // Expr=DeclRef(U),
- // Type=decltype(T)))
- // Then we substitute T = 2, U = 'a' into the parameter mapping, and need to
- // produce:
- // AtomicExpr(sizeof(U) == 4,
- // U=SubstNonTypeTemplateParmExpr(Param=U,
- // Expr=ImpCast(
- // decltype(2),
- // SubstNTTPE(Param=U, Expr='a',
- // Type=char)),
- // Type=decltype(2)))
- // The call to CheckTemplateArgument here produces the ImpCast.
- TemplateArgument SugaredConverted, CanonicalConverted;
- if (SemaRef
- .CheckTemplateArgument(E->getParameter(), SubstType,
- SubstReplacement.get(), SugaredConverted,
- CanonicalConverted,
- /*StrictCheck=*/false, Sema::CTAK_Specified)
- .isInvalid())
- return true;
- return transformNonTypeTemplateParmRef(
- E->getAssociatedDecl(), E->getParameter(), E->getExprLoc(),
- SugaredConverted, E->getPackIndex(), E->getFinal());
-}
-
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(ValueDecl *PD,
SourceLocation Loc) {
DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
@@ -2701,8 +2536,8 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
}
// PackIndex starts from last element.
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
assert(Arg.getKind() == TemplateArgument::Type &&
@@ -2749,20 +2584,20 @@ QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
}
TemplateArgument Pack = T->getArgumentPack();
- TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
+ TemplateArgument Arg = SemaRef.getPackSubstitutedTemplateArgument(Pack);
return BuildSubstTemplateTypeParmType(
TLB, SuppressObjCLifetime, T->getFinal(), NewReplaced, T->getIndex(),
- getPackIndex(Pack), Arg, TL.getNameLoc());
+ SemaRef.getPackIndex(Pack), Arg, TL.getNameLoc());
}
QualType TemplateInstantiator::TransformSubstBuiltinTemplatePackType(
TypeLocBuilder &TLB, SubstBuiltinTemplatePackTypeLoc TL) {
if (!getSema().ArgPackSubstIndex)
return TreeTransform::TransformSubstBuiltinTemplatePackType(TLB, TL);
- auto &Sema = getSema();
- TemplateArgument Result = getPackSubstitutedTemplateArgument(
- Sema, TL.getTypePtr()->getArgumentPack());
- TLB.pushTrivial(Sema.getASTContext(), Result.getAsType(), TL.getBeginLoc());
+ TemplateArgument Result = SemaRef.getPackSubstitutedTemplateArgument(
+ TL.getTypePtr()->getArgumentPack());
+ TLB.pushTrivial(SemaRef.getASTContext(), Result.getAsType(),
+ TL.getBeginLoc());
return Result.getAsType();
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index adac3dff5b2b4..e2dc70360506e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3742,7 +3742,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
ExpandedParams.reserve(D->getNumExpansionTemplateParameters());
for (unsigned I = 0, N = D->getNumExpansionTemplateParameters();
I != N; ++I) {
- LocalInstantiationScope Scope(SemaRef);
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
TemplateParameterList *Expansion ...
[truncated]
|
@llvm/pr-subscribers-clang Author: Matheus Izvekov (mizvekov) ChangesThis simplifies those transforms a lot, removing a bunch of workarounds which were introducing problems. The transforms become independent of the template instantiator, so they are moved to TreeTransform instead. Fixes #131342 This PR was already reviewed and approved at #160777, but I accidentally merged that into another PR, instead of main. Patch is 28.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/161029.diff 13 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6cfe42b5dc9f8..98c889c08b329 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -361,6 +361,7 @@ Bug Fixes in This Version
first parameter. (#GH113323).
- Fixed a crash with incompatible pointer to integer conversions in designated
initializers involving string literals. (#GH154046)
+- Fix crash on CTAD for alias template. (#GH131342)
- Clang now emits a frontend error when a function marked with the `flatten` attribute
calls another function that requires target features not enabled in the caller. This
prevents a fatal error in the backend.
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 9fedb230ce397..5f16bac94d5e6 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -4714,7 +4714,7 @@ class SubstNonTypeTemplateParmExpr : public Expr {
// sugared: it doesn't need to be resugared later.
bool getFinal() const { return Final; }
- NamedDecl *getParameter() const;
+ NonTypeTemplateParmDecl *getParameter() const;
bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); }
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index b02d9c7499fe5..e0d00b82f2b76 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -3495,7 +3495,9 @@ class AdjustedType : public Type, public llvm::FoldingSetNode {
AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy,
QualType CanonicalPtr)
- : Type(TC, CanonicalPtr, OriginalTy->getDependence()),
+ : Type(TC, CanonicalPtr,
+ AdjustedTy->getDependence() |
+ (OriginalTy->getDependence() & ~TypeDependence::Dependent)),
OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {}
public:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5edfc29d93781..2bd6be2a32cd5 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11714,6 +11714,23 @@ class Sema final : public SemaBase {
const TemplateArgumentListInfo *TemplateArgs,
bool IsAddressOfOperand);
+ UnsignedOrNone getPackIndex(TemplateArgument Pack) const {
+ return Pack.pack_size() - 1 - *ArgPackSubstIndex;
+ }
+
+ TemplateArgument
+ getPackSubstitutedTemplateArgument(TemplateArgument Arg) const {
+ Arg = Arg.pack_elements()[*ArgPackSubstIndex];
+ if (Arg.isPackExpansion())
+ Arg = Arg.getPackExpansionPattern();
+ return Arg;
+ }
+
+ ExprResult BuildSubstNonTypeTemplateParmExpr(
+ Decl *AssociatedDecl, const NonTypeTemplateParmDecl *NTTP,
+ SourceLocation loc, TemplateArgument Replacement,
+ UnsignedOrNone PackIndex, bool Final);
+
/// Form a template name from a name that is syntactically required to name a
/// template, either due to use of the 'template' keyword or because a name in
/// this syntactic context is assumed to name a template (C++
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 97ae4a07f32aa..95de6a82a5270 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1725,8 +1725,8 @@ SizeOfPackExpr *SizeOfPackExpr::CreateDeserialized(ASTContext &Context,
return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs);
}
-NamedDecl *SubstNonTypeTemplateParmExpr::getParameter() const {
- return cast<NamedDecl>(
+NonTypeTemplateParmDecl *SubstNonTypeTemplateParmExpr::getParameter() const {
+ return cast<NonTypeTemplateParmDecl>(
getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]);
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 37c4d43ec0b2f..8b3af94e1a8bc 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1353,7 +1353,8 @@ void StmtProfiler::VisitExpr(const Expr *S) {
}
void StmtProfiler::VisitConstantExpr(const ConstantExpr *S) {
- VisitExpr(S);
+ // Profile exactly as the sub-expression.
+ Visit(S->getSubExpr());
}
void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 91e4dc8a2d039..3ebbb30ae483e 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -775,6 +775,40 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
TemplateArgs);
}
+ExprResult Sema::BuildSubstNonTypeTemplateParmExpr(
+ Decl *AssociatedDecl, const NonTypeTemplateParmDecl *NTTP,
+ SourceLocation Loc, TemplateArgument Arg, UnsignedOrNone PackIndex,
+ bool Final) {
+ // The template argument itself might be an expression, in which case we just
+ // return that expression. This happens when substituting into an alias
+ // template.
+ Expr *Replacement;
+ bool refParam = true;
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ Replacement = Arg.getAsExpr();
+ refParam = Replacement->isLValue();
+ if (refParam && Replacement->getType()->isRecordType()) {
+ QualType ParamType =
+ NTTP->isExpandedParameterPack()
+ ? NTTP->getExpansionType(*SemaRef.ArgPackSubstIndex)
+ : NTTP->getType();
+ if (const auto *PET = dyn_cast<PackExpansionType>(ParamType))
+ ParamType = PET->getPattern();
+ refParam = ParamType->isReferenceType();
+ }
+ } else {
+ ExprResult result =
+ SemaRef.BuildExpressionFromNonTypeTemplateArgument(Arg, Loc);
+ if (result.isInvalid())
+ return ExprError();
+ Replacement = result.get();
+ refParam = Arg.getNonTypeTemplateArgumentType()->isReferenceType();
+ }
+ return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
+ Replacement->getType(), Replacement->getValueKind(), Loc, Replacement,
+ AssociatedDecl, NTTP->getIndex(), PackIndex, refParam, Final);
+}
+
bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
NamedDecl *Instantiation,
bool InstantiatedFromMember,
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a72c95d6d77cf..1ff94d7ae397f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1373,16 +1373,6 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
return std::nullopt;
}
-static TemplateArgument
-getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
- assert(S.ArgPackSubstIndex);
- assert(*S.ArgPackSubstIndex < Arg.pack_size());
- Arg = Arg.pack_begin()[*S.ArgPackSubstIndex];
- if (Arg.isPackExpansion())
- Arg = Arg.getPackExpansionPattern();
- return Arg;
-}
-
//===----------------------------------------------------------------------===/
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
@@ -1449,13 +1439,6 @@ namespace {
return TemplateArgs.getNewDepth(Depth);
}
- UnsignedOrNone getPackIndex(TemplateArgument Pack) {
- UnsignedOrNone Index = getSema().ArgPackSubstIndex;
- if (!Index)
- return std::nullopt;
- return Pack.pack_size() - 1 - *Index;
- }
-
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
@@ -1537,7 +1520,7 @@ namespace {
if (TA.getKind() != TemplateArgument::Pack)
return TA;
if (SemaRef.ArgPackSubstIndex)
- return getPackSubstitutedTemplateArgument(SemaRef, TA);
+ return SemaRef.getPackSubstitutedTemplateArgument(TA);
assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
"unexpected pack arguments in template rewrite");
TemplateArgument Arg = *TA.pack_begin();
@@ -1643,10 +1626,6 @@ namespace {
ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *D);
- ExprResult TransformSubstNonTypeTemplateParmPackExpr(
- SubstNonTypeTemplateParmPackExpr *E);
- ExprResult TransformSubstNonTypeTemplateParmExpr(
- SubstNonTypeTemplateParmExpr *E);
/// Rebuild a DeclRefExpr for a VarDecl reference.
ExprResult RebuildVarDeclRefExpr(ValueDecl *PD, SourceLocation Loc);
@@ -1933,12 +1912,6 @@ namespace {
SmallVectorImpl<QualType> &PTypes,
SmallVectorImpl<ParmVarDecl *> &TransParams,
Sema::ExtParameterInfoBuilder &PInfos);
-
- private:
- ExprResult
- transformNonTypeTemplateParmRef(Decl *AssociatedDecl, const NamedDecl *parm,
- SourceLocation loc, TemplateArgument arg,
- UnsignedOrNone PackIndex, bool Final);
};
}
@@ -1975,7 +1948,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
TemplateName Template = Arg.getAsTemplate();
@@ -2079,7 +2052,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
if (!getSema().ArgPackSubstIndex)
return nullptr;
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
QualType T = Arg.getAsType();
@@ -2165,8 +2138,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
Arg, AssociatedDecl, TTP->getIndex(), Final);
}
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
TemplateName Template = Arg.getAsTemplate();
@@ -2183,10 +2156,10 @@ TemplateName TemplateInstantiator::TransformTemplateName(
TemplateArgument Pack = SubstPack->getArgumentPack();
TemplateName Template =
- getPackSubstitutedTemplateArgument(getSema(), Pack).getAsTemplate();
+ SemaRef.getPackSubstitutedTemplateArgument(Pack).getAsTemplate();
return getSema().Context.getSubstTemplateTemplateParm(
Template, SubstPack->getAssociatedDecl(), SubstPack->getIndex(),
- getPackIndex(Pack), SubstPack->getFinal());
+ SemaRef.getPackIndex(Pack), SubstPack->getFinal());
}
return inherited::TransformTemplateName(
@@ -2252,11 +2225,11 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition(), Final);
}
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
- return transformNonTypeTemplateParmRef(AssociatedDecl, NTTP, E->getLocation(),
- Arg, PackIndex, Final);
+ return SemaRef.BuildSubstNonTypeTemplateParmExpr(
+ AssociatedDecl, NTTP, E->getLocation(), Arg, PackIndex, Final);
}
const AnnotateAttr *
@@ -2344,144 +2317,6 @@ TemplateInstantiator::TransformOpenACCRoutineDeclAttr(
"applies to a Function Decl (and a few places for VarDecl)");
}
-ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
- Decl *AssociatedDecl, const NamedDecl *parm, SourceLocation loc,
- TemplateArgument arg, UnsignedOrNone PackIndex, bool Final) {
- ExprResult result;
-
- // Determine the substituted parameter type. We can usually infer this from
- // the template argument, but not always.
- auto SubstParamType = [&] {
- if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(parm)) {
- QualType T;
- if (NTTP->isExpandedParameterPack())
- T = NTTP->getExpansionType(*SemaRef.ArgPackSubstIndex);
- else
- T = NTTP->getType();
- if (parm->isParameterPack() && isa<PackExpansionType>(T))
- T = cast<PackExpansionType>(T)->getPattern();
- return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName());
- }
- return SemaRef.SubstType(arg.getAsExpr()->getType(), TemplateArgs, loc,
- parm->getDeclName());
- };
-
- bool refParam = false;
-
- // The template argument itself might be an expression, in which case we just
- // return that expression. This happens when substituting into an alias
- // template.
- if (arg.getKind() == TemplateArgument::Expression) {
- Expr *argExpr = arg.getAsExpr();
- result = argExpr;
- if (argExpr->isLValue()) {
- if (argExpr->getType()->isRecordType()) {
- // Check whether the parameter was actually a reference.
- QualType paramType = SubstParamType();
- if (paramType.isNull())
- return ExprError();
- refParam = paramType->isReferenceType();
- } else {
- refParam = true;
- }
- }
- } else if (arg.getKind() == TemplateArgument::Declaration ||
- arg.getKind() == TemplateArgument::NullPtr) {
- if (arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = arg.getAsDecl();
-
- // Find the instantiation of the template argument. This is
- // required for nested templates.
- VD = cast_or_null<ValueDecl>(
- getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
- if (!VD)
- return ExprError();
- }
-
- QualType paramType = arg.getNonTypeTemplateArgumentType();
- assert(!paramType.isNull() && "type substitution failed for param type");
- assert(!paramType->isDependentType() && "param type still dependent");
- result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
- refParam = paramType->isReferenceType();
- } else {
- QualType paramType = arg.getNonTypeTemplateArgumentType();
- result = SemaRef.BuildExpressionFromNonTypeTemplateArgument(arg, loc);
- refParam = paramType->isReferenceType();
- assert(result.isInvalid() ||
- SemaRef.Context.hasSameType(result.get()->getType(),
- paramType.getNonReferenceType()));
- }
-
- if (result.isInvalid())
- return ExprError();
-
- Expr *resultExpr = result.get();
- return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
- resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr,
- AssociatedDecl,
- clang::getDepthAndIndex(const_cast<NamedDecl *>(parm)).second, PackIndex,
- refParam, Final);
-}
-
-ExprResult
-TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
- SubstNonTypeTemplateParmPackExpr *E) {
- if (!getSema().ArgPackSubstIndex) {
- // We aren't expanding the parameter pack, so just return ourselves.
- return E;
- }
-
- TemplateArgument Pack = E->getArgumentPack();
- TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
- return transformNonTypeTemplateParmRef(
- E->getAssociatedDecl(), E->getParameterPack(),
- E->getParameterPackLocation(), Arg, getPackIndex(Pack), E->getFinal());
-}
-
-ExprResult
-TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
- SubstNonTypeTemplateParmExpr *E) {
- ExprResult SubstReplacement = E->getReplacement();
- if (!isa<ConstantExpr>(SubstReplacement.get()))
- SubstReplacement = TransformExpr(E->getReplacement());
- if (SubstReplacement.isInvalid())
- return true;
- QualType SubstType = TransformType(E->getParameterType(getSema().Context));
- if (SubstType.isNull())
- return true;
- // The type may have been previously dependent and not now, which means we
- // might have to implicit cast the argument to the new type, for example:
- // template<auto T, decltype(T) U>
- // concept C = sizeof(U) == 4;
- // void foo() requires C<2, 'a'> { }
- // When normalizing foo(), we first form the normalized constraints of C:
- // AtomicExpr(sizeof(U) == 4,
- // U=SubstNonTypeTemplateParmExpr(Param=U,
- // Expr=DeclRef(U),
- // Type=decltype(T)))
- // Then we substitute T = 2, U = 'a' into the parameter mapping, and need to
- // produce:
- // AtomicExpr(sizeof(U) == 4,
- // U=SubstNonTypeTemplateParmExpr(Param=U,
- // Expr=ImpCast(
- // decltype(2),
- // SubstNTTPE(Param=U, Expr='a',
- // Type=char)),
- // Type=decltype(2)))
- // The call to CheckTemplateArgument here produces the ImpCast.
- TemplateArgument SugaredConverted, CanonicalConverted;
- if (SemaRef
- .CheckTemplateArgument(E->getParameter(), SubstType,
- SubstReplacement.get(), SugaredConverted,
- CanonicalConverted,
- /*StrictCheck=*/false, Sema::CTAK_Specified)
- .isInvalid())
- return true;
- return transformNonTypeTemplateParmRef(
- E->getAssociatedDecl(), E->getParameter(), E->getExprLoc(),
- SugaredConverted, E->getPackIndex(), E->getFinal());
-}
-
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(ValueDecl *PD,
SourceLocation Loc) {
DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
@@ -2701,8 +2536,8 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
}
// PackIndex starts from last element.
- PackIndex = getPackIndex(Arg);
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ PackIndex = SemaRef.getPackIndex(Arg);
+ Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
assert(Arg.getKind() == TemplateArgument::Type &&
@@ -2749,20 +2584,20 @@ QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
}
TemplateArgument Pack = T->getArgumentPack();
- TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
+ TemplateArgument Arg = SemaRef.getPackSubstitutedTemplateArgument(Pack);
return BuildSubstTemplateTypeParmType(
TLB, SuppressObjCLifetime, T->getFinal(), NewReplaced, T->getIndex(),
- getPackIndex(Pack), Arg, TL.getNameLoc());
+ SemaRef.getPackIndex(Pack), Arg, TL.getNameLoc());
}
QualType TemplateInstantiator::TransformSubstBuiltinTemplatePackType(
TypeLocBuilder &TLB, SubstBuiltinTemplatePackTypeLoc TL) {
if (!getSema().ArgPackSubstIndex)
return TreeTransform::TransformSubstBuiltinTemplatePackType(TLB, TL);
- auto &Sema = getSema();
- TemplateArgument Result = getPackSubstitutedTemplateArgument(
- Sema, TL.getTypePtr()->getArgumentPack());
- TLB.pushTrivial(Sema.getASTContext(), Result.getAsType(), TL.getBeginLoc());
+ TemplateArgument Result = SemaRef.getPackSubstitutedTemplateArgument(
+ TL.getTypePtr()->getArgumentPack());
+ TLB.pushTrivial(SemaRef.getASTContext(), Result.getAsType(),
+ TL.getBeginLoc());
return Result.getAsType();
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index adac3dff5b2b4..e2dc70360506e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3742,7 +3742,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
ExpandedParams.reserve(D->getNumExpansionTemplateParameters());
for (unsigned I = 0, N = D->getNumExpansionTemplateParameters();
I != N; ++I) {
- LocalInstantiationScope Scope(SemaRef);
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
TemplateParameterList *Expansion ...
[truncated]
|
This simplifies those transforms a lot, removing a bunch of workarounds which were introducing problems. The transforms become independent of the template instantiator, so they are moved to TreeTransform instead. Fixes #131342
c12df7c
to
41fb95c
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/24/builds/13097 Here is the relevant piece of the build log for the reference
|
…llvm#161029) This simplifies those transforms a lot, removing a bunch of workarounds which were introducing problems. The transforms become independent of the template instantiator, so they are moved to TreeTransform instead. Fixes llvm#131342 This PR was already reviewed and approved at llvm#160777, but I accidentally merged that into another PR, instead of main.
Hi @mizvekov , it looks like this commit is causing a crash in Clang CodeGen. I'm working on a test case. |
@mizvekov the reduction went slightly wrong and resulted in invalid code (though the original code used to compile and work without any obvious issues): https://gcc.godbolt.org/z/dWEej5qb6
Crash call stack:
I'll try to repeat the process with a stricter interestingness test, but please take a look at the test case above - it still may be useful in understanding what happens. |
@mizvekov now a better test case, which compiles before this commit: https://gcc.godbolt.org/z/qhaTEEr3P
|
This simplifies those transforms a lot, removing a bunch of workarounds which were introducing problems.
The transforms become independent of the template instantiator, so they are moved to TreeTransform instead.
Fixes #131342
This PR was already reviewed and approved at #160777, but I accidentally merged that into another PR, instead of main.