diff options
author | Younan Zhang <zyn7109@gmail.com> | 2024-11-07 15:37:14 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-07 15:37:14 +0800 |
commit | adb0d8ddceb143749c519d14b8b31b481071da77 (patch) | |
tree | 3da82720a5923229fb82b267a0f272d18e1ad3db | |
parent | 9f796159f28775b3f93d77e173c1fd3413c2e60e (diff) | |
download | llvm-adb0d8ddceb143749c519d14b8b31b481071da77.zip llvm-adb0d8ddceb143749c519d14b8b31b481071da77.tar.gz llvm-adb0d8ddceb143749c519d14b8b31b481071da77.tar.bz2 |
[Clang] Distinguish expanding-pack-in-place cases for SubstTemplateTypeParmTypes (#114220)
In 50e5411e4, we preserved the pack substitution index within
SubstTemplateTypeParmType nodes and performed in-place expansions of
packs such that type constraints on a lambda that serve as a pattern of
a fold expression could be evaluated if the type constraints contain any
packs that are expanded by the fold expression.
However, we made an incorrect assumption of the condition under which
in-place expansion should occur. For example, a SizeOfPackExpr case
relies on SubstTemplateTypeParmType nodes being transformed to
SubstTemplateTypeParmPackTypes rather than expanding them immediately in
place.
This fixes that by adding a flag to SubstTemplateTypeParmType to
discriminate such in-place expansion situations.
Fixes https://github.com/llvm/llvm-project/issues/113518
-rw-r--r-- | clang/include/clang/AST/ASTContext.h | 4 | ||||
-rw-r--r-- | clang/include/clang/AST/PropertiesBase.td | 1 | ||||
-rw-r--r-- | clang/include/clang/AST/Type.h | 29 | ||||
-rw-r--r-- | clang/include/clang/AST/TypeProperties.td | 5 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 7 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 35 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 19 |
9 files changed, 88 insertions, 22 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index dfd5bd8a..89fcb67 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1747,7 +1747,9 @@ public: QualType getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl, unsigned Index, - std::optional<unsigned> PackIndex) const; + std::optional<unsigned> PackIndex, + SubstTemplateTypeParmTypeFlag Flag = + SubstTemplateTypeParmTypeFlag::None) const; QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl, unsigned Index, bool Final, const TemplateArgument &ArgPack); diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 5f3a885..42883b6 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -137,6 +137,7 @@ def Selector : PropertyType; def SourceLocation : PropertyType; def StmtRef : RefPropertyType<"Stmt"> { let ConstWhenWriting = 1; } def ExprRef : SubclassPropertyType<"Expr", StmtRef>; +def SubstTemplateTypeParmTypeFlag : EnumPropertyType; def TemplateArgument : PropertyType; def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">; def TemplateName : DefaultValuePropertyType; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 1bcc7ee..8979129 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1802,6 +1802,15 @@ enum class AutoTypeKeyword { GNUAutoType }; +enum class SubstTemplateTypeParmTypeFlag { + None, + + /// Whether to expand the pack using the stored PackIndex in place. This is + /// useful for e.g. substituting into an atomic constraint expression, where + /// that expression is part of an unexpanded pack. + ExpandPacksInPlace, +}; + enum class ArraySizeModifier; enum class ElaboratedTypeKeyword; enum class VectorKind; @@ -2171,6 +2180,9 @@ protected: LLVM_PREFERRED_TYPE(bool) unsigned HasNonCanonicalUnderlyingType : 1; + LLVM_PREFERRED_TYPE(SubstTemplateTypeParmTypeFlag) + unsigned SubstitutionFlag : 1; + // The index of the template parameter this substitution represents. unsigned Index : 15; @@ -6387,7 +6399,8 @@ class SubstTemplateTypeParmType final Decl *AssociatedDecl; SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl, - unsigned Index, std::optional<unsigned> PackIndex); + unsigned Index, std::optional<unsigned> PackIndex, + SubstTemplateTypeParmTypeFlag Flag); public: /// Gets the type that was substituted for the template @@ -6416,21 +6429,31 @@ public: return SubstTemplateTypeParmTypeBits.PackIndex - 1; } + SubstTemplateTypeParmTypeFlag getSubstitutionFlag() const { + return static_cast<SubstTemplateTypeParmTypeFlag>( + SubstTemplateTypeParmTypeBits.SubstitutionFlag); + } + bool isSugared() const { return true; } QualType desugar() const { return getReplacementType(); } void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(), - getPackIndex()); + getPackIndex(), getSubstitutionFlag()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement, const Decl *AssociatedDecl, unsigned Index, - std::optional<unsigned> PackIndex) { + std::optional<unsigned> PackIndex, + SubstTemplateTypeParmTypeFlag Flag) { Replacement.Profile(ID); ID.AddPointer(AssociatedDecl); ID.AddInteger(Index); ID.AddInteger(PackIndex ? *PackIndex - 1 : 0); + ID.AddInteger(llvm::to_underlying(Flag)); + assert((Flag != SubstTemplateTypeParmTypeFlag::ExpandPacksInPlace || + PackIndex) && + "ExpandPacksInPlace needs a valid PackIndex"); } static bool classof(const Type *T) { diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index 42f6269..a8b9c92 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -824,11 +824,14 @@ let Class = SubstTemplateTypeParmType in { def : Property<"PackIndex", Optional<UInt32>> { let Read = [{ node->getPackIndex() }]; } + def : Property<"SubstitutionFlag", SubstTemplateTypeParmTypeFlag> { + let Read = [{ node->getSubstitutionFlag() }]; + } // The call to getCanonicalType here existed in ASTReader.cpp, too. def : Creator<[{ return ctx.getSubstTemplateTypeParmType( - replacementType, associatedDecl, Index, PackIndex); + replacementType, associatedDecl, Index, PackIndex, SubstitutionFlag); }]>; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 68ddbc5..09d159e 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5303,10 +5303,11 @@ QualType ASTContext::getHLSLAttributedResourceType( /// Retrieve a substitution-result type. QualType ASTContext::getSubstTemplateTypeParmType( QualType Replacement, Decl *AssociatedDecl, unsigned Index, - std::optional<unsigned> PackIndex) const { + std::optional<unsigned> PackIndex, + SubstTemplateTypeParmTypeFlag Flag) const { llvm::FoldingSetNodeID ID; SubstTemplateTypeParmType::Profile(ID, Replacement, AssociatedDecl, Index, - PackIndex); + PackIndex, Flag); void *InsertPos = nullptr; SubstTemplateTypeParmType *SubstParm = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -5316,7 +5317,7 @@ QualType ASTContext::getSubstTemplateTypeParmType( !Replacement.isCanonical()), alignof(SubstTemplateTypeParmType)); SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, AssociatedDecl, - Index, PackIndex); + Index, PackIndex, Flag); Types.push_back(SubstParm); SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 6e31df6..35aba41 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1628,8 +1628,8 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType( return ToReplacementTypeOrErr.takeError(); return Importer.getToContext().getSubstTemplateTypeParmType( - *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), - T->getPackIndex()); + *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), T->getPackIndex(), + T->getSubstitutionFlag()); } ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType( diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 6bf2908..7de1397 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -4219,7 +4219,7 @@ static const TemplateTypeParmDecl *getReplacedParameter(Decl *D, SubstTemplateTypeParmType::SubstTemplateTypeParmType( QualType Replacement, Decl *AssociatedDecl, unsigned Index, - std::optional<unsigned> PackIndex) + std::optional<unsigned> PackIndex, SubstTemplateTypeParmTypeFlag Flag) : Type(SubstTemplateTypeParm, Replacement.getCanonicalType(), Replacement->getDependence()), AssociatedDecl(AssociatedDecl) { @@ -4230,6 +4230,10 @@ SubstTemplateTypeParmType::SubstTemplateTypeParmType( SubstTemplateTypeParmTypeBits.Index = Index; SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0; + SubstTemplateTypeParmTypeBits.SubstitutionFlag = llvm::to_underlying(Flag); + assert((Flag != SubstTemplateTypeParmTypeFlag::ExpandPacksInPlace || + PackIndex) && + "ExpandPacksInPlace needs a valid PackIndex"); assert(AssociatedDecl != nullptr); } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index b3ae965..b1b92c0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1661,14 +1661,17 @@ namespace { QualType TransformSubstTemplateTypeParmType(TypeLocBuilder &TLB, SubstTemplateTypeParmTypeLoc TL) { - if (SemaRef.CodeSynthesisContexts.back().Kind != - Sema::CodeSynthesisContext::ConstraintSubstitution) + const SubstTemplateTypeParmType *Type = TL.getTypePtr(); + if (Type->getSubstitutionFlag() != + SubstTemplateTypeParmTypeFlag::ExpandPacksInPlace) return inherited::TransformSubstTemplateTypeParmType(TLB, TL); - auto PackIndex = TL.getTypePtr()->getPackIndex(); - std::optional<Sema::ArgumentPackSubstitutionIndexRAII> SubstIndex; - if (SemaRef.ArgumentPackSubstitutionIndex == -1 && PackIndex) - SubstIndex.emplace(SemaRef, *PackIndex); + assert(Type->getPackIndex()); + TemplateArgument TA = TemplateArgs( + Type->getReplacedParameter()->getDepth(), Type->getIndex()); + assert(*Type->getPackIndex() + 1 <= TA.pack_size()); + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex( + SemaRef, TA.pack_size() - 1 - *Type->getPackIndex()); return inherited::TransformSubstTemplateTypeParmType(TLB, TL); } @@ -3147,7 +3150,11 @@ struct ExpandPackedTypeConstraints using inherited = TreeTransform<ExpandPackedTypeConstraints>; - ExpandPackedTypeConstraints(Sema &SemaRef) : inherited(SemaRef) {} + const MultiLevelTemplateArgumentList &TemplateArgs; + + ExpandPackedTypeConstraints( + Sema &SemaRef, const MultiLevelTemplateArgumentList &TemplateArgs) + : inherited(SemaRef), TemplateArgs(TemplateArgs) {} using inherited::TransformTemplateTypeParmType; @@ -3163,9 +3170,15 @@ struct ExpandPackedTypeConstraints assert(SemaRef.ArgumentPackSubstitutionIndex != -1); + TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex()); + + std::optional<unsigned> PackIndex; + if (Arg.getKind() == TemplateArgument::Pack) + PackIndex = Arg.pack_size() - 1 - SemaRef.ArgumentPackSubstitutionIndex; + QualType Result = SemaRef.Context.getSubstTemplateTypeParmType( - TL.getType(), T->getDecl(), T->getIndex(), - SemaRef.ArgumentPackSubstitutionIndex); + TL.getType(), T->getDecl(), T->getIndex(), PackIndex, + SubstTemplateTypeParmTypeFlag::ExpandPacksInPlace); SubstTemplateTypeParmTypeLoc NewTL = TLB.push<SubstTemplateTypeParmTypeLoc>(Result); NewTL.setNameLoc(TL.getNameLoc()); @@ -3224,8 +3237,8 @@ bool Sema::SubstTypeConstraint( TemplateArgumentListInfo InstArgs; InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); - if (ExpandPackedTypeConstraints(*this).SubstTemplateArguments( - TemplArgInfo->arguments(), InstArgs)) + if (ExpandPackedTypeConstraints(*this, TemplateArgs) + .SubstTemplateArguments(TemplArgInfo->arguments(), InstArgs)) return true; // The type of the original parameter. diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 675c32a..2d43e46 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -494,3 +494,22 @@ template <typename V> using Alias = S<V>; Alias A(42); } // namespace GH111508 + +namespace GH113518 { + +template <class T, unsigned N> struct array { + T value[N]; +}; + +template <typename Tp, typename... Up> +array(Tp, Up...) -> array<Tp, 1 + sizeof...(Up)>; + +template <typename T> struct ArrayType { + template <unsigned size> using Array = array<T, size>; +}; + +template <ArrayType<int>::Array array> void test() {} + +void foo() { test<{1, 2, 3}>(); } + +} // namespace GH113518 |