Skip to content

Commit 0077d4c

Browse files
authored
[Clang] Fix pack indexing profiling (#139276)
When profiling a pack indexing that has been partially substituted, we should profile the expansions, rather than the pattern itseld This is a better approach to #139057 This mirrors the fix done for SizeOfPackExpr in #124533 Fixes #138255
1 parent 8e9227a commit 0077d4c

File tree

8 files changed

+118
-27
lines changed

8 files changed

+118
-27
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,7 @@ Bug Fixes to C++ Support
679679
whose type depends on itself. (#GH51347), (#GH55872)
680680
- Improved parser recovery of invalid requirement expressions. In turn, this
681681
fixes crashes from follow-on processing of the invalid requirement. (#GH138820)
682+
- Fixed the handling of pack indexing types in the constraints of a member function redeclaration. (#GH138255)
682683

683684
Bug Fixes to AST Handling
684685
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/AST/ASTContext.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
221221
mutable llvm::ContextualFoldingSet<DependentDecltypeType, ASTContext &>
222222
DependentDecltypeTypes;
223223

224-
mutable llvm::FoldingSet<PackIndexingType> DependentPackIndexingTypes;
224+
mutable llvm::ContextualFoldingSet<PackIndexingType, ASTContext &>
225+
DependentPackIndexingTypes;
225226

226227
mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
227228
mutable llvm::FoldingSet<ObjCTypeParamType> ObjCTypeParamTypes;

clang/include/clang/AST/ExprCXX.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4547,6 +4547,7 @@ class PackIndexingExpr final
45474547
static PackIndexingExpr *CreateDeserialized(ASTContext &Context,
45484548
unsigned NumTransformedExprs);
45494549

4550+
// The index expression and all elements of the pack have been substituted.
45504551
bool isFullySubstituted() const { return FullySubstituted; }
45514552

45524553
/// Determine if the expression was expanded to empty.

clang/include/clang/AST/Type.h

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5976,7 +5976,6 @@ class PackIndexingType final
59765976
private llvm::TrailingObjects<PackIndexingType, QualType> {
59775977
friend TrailingObjects;
59785978

5979-
const ASTContext &Context;
59805979
QualType Pattern;
59815980
Expr *IndexExpr;
59825981

@@ -5987,9 +5986,8 @@ class PackIndexingType final
59875986

59885987
protected:
59895988
friend class ASTContext; // ASTContext creates these.
5990-
PackIndexingType(const ASTContext &Context, QualType Canonical,
5991-
QualType Pattern, Expr *IndexExpr, bool FullySubstituted,
5992-
ArrayRef<QualType> Expansions = {});
5989+
PackIndexingType(QualType Canonical, QualType Pattern, Expr *IndexExpr,
5990+
bool FullySubstituted, ArrayRef<QualType> Expansions = {});
59935991

59945992
public:
59955993
Expr *getIndexExpr() const { return IndexExpr; }
@@ -6024,14 +6022,10 @@ class PackIndexingType final
60246022
return T->getTypeClass() == PackIndexing;
60256023
}
60266024

6027-
void Profile(llvm::FoldingSetNodeID &ID) {
6028-
if (hasSelectedType())
6029-
getSelectedType().Profile(ID);
6030-
else
6031-
Profile(ID, Context, getPattern(), getIndexExpr(), isFullySubstituted());
6032-
}
6025+
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context);
60336026
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
6034-
QualType Pattern, Expr *E, bool FullySubstituted);
6027+
QualType Pattern, Expr *E, bool FullySubstituted,
6028+
ArrayRef<QualType> Expansions);
60356029

60366030
private:
60376031
const QualType *getExpansionsPtr() const {

clang/lib/AST/ASTContext.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
940940
DependentSizedMatrixTypes(this_()),
941941
FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize),
942942
DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()),
943-
TemplateSpecializationTypes(this_()),
943+
DependentPackIndexingTypes(this_()), TemplateSpecializationTypes(this_()),
944944
DependentTemplateSpecializationTypes(this_()),
945945
DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()),
946946
DeducedTemplates(this_()), ArrayParameterTypes(this_()),
@@ -6438,17 +6438,17 @@ QualType ASTContext::getPackIndexingType(QualType Pattern, Expr *IndexExpr,
64386438
} else {
64396439
llvm::FoldingSetNodeID ID;
64406440
PackIndexingType::Profile(ID, *this, Pattern.getCanonicalType(), IndexExpr,
6441-
FullySubstituted);
6441+
FullySubstituted, Expansions);
64426442
void *InsertPos = nullptr;
64436443
PackIndexingType *Canon =
64446444
DependentPackIndexingTypes.FindNodeOrInsertPos(ID, InsertPos);
64456445
if (!Canon) {
64466446
void *Mem = Allocate(
64476447
PackIndexingType::totalSizeToAlloc<QualType>(Expansions.size()),
64486448
TypeAlignment);
6449-
Canon = new (Mem)
6450-
PackIndexingType(*this, QualType(), Pattern.getCanonicalType(),
6451-
IndexExpr, FullySubstituted, Expansions);
6449+
Canon =
6450+
new (Mem) PackIndexingType(QualType(), Pattern.getCanonicalType(),
6451+
IndexExpr, FullySubstituted, Expansions);
64526452
DependentPackIndexingTypes.InsertNode(Canon, InsertPos);
64536453
}
64546454
Canonical = QualType(Canon, 0);
@@ -6457,7 +6457,7 @@ QualType ASTContext::getPackIndexingType(QualType Pattern, Expr *IndexExpr,
64576457
void *Mem =
64586458
Allocate(PackIndexingType::totalSizeToAlloc<QualType>(Expansions.size()),
64596459
TypeAlignment);
6460-
auto *T = new (Mem) PackIndexingType(*this, Canonical, Pattern, IndexExpr,
6460+
auto *T = new (Mem) PackIndexingType(Canonical, Pattern, IndexExpr,
64616461
FullySubstituted, Expansions);
64626462
Types.push_back(T);
64636463
return QualType(T, 0);

clang/lib/AST/StmtProfile.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,9 +2291,15 @@ void StmtProfiler::VisitSizeOfPackExpr(const SizeOfPackExpr *S) {
22912291
}
22922292

22932293
void StmtProfiler::VisitPackIndexingExpr(const PackIndexingExpr *E) {
2294-
VisitExpr(E);
2295-
VisitExpr(E->getPackIdExpression());
22962294
VisitExpr(E->getIndexExpr());
2295+
2296+
if (E->expandsToEmptyPack() || E->getExpressions().size() != 0) {
2297+
ID.AddInteger(E->getExpressions().size());
2298+
for (const Expr *Sub : E->getExpressions())
2299+
Visit(Sub);
2300+
} else {
2301+
VisitExpr(E->getPackIdExpression());
2302+
}
22972303
}
22982304

22992305
void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr(

clang/lib/AST/Type.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4125,14 +4125,14 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
41254125
E->Profile(ID, Context, true);
41264126
}
41274127

4128-
PackIndexingType::PackIndexingType(const ASTContext &Context,
4129-
QualType Canonical, QualType Pattern,
4128+
PackIndexingType::PackIndexingType(QualType Canonical, QualType Pattern,
41304129
Expr *IndexExpr, bool FullySubstituted,
41314130
ArrayRef<QualType> Expansions)
41324131
: Type(PackIndexing, Canonical,
41334132
computeDependence(Pattern, IndexExpr, Expansions)),
4134-
Context(Context), Pattern(Pattern), IndexExpr(IndexExpr),
4135-
Size(Expansions.size()), FullySubstituted(FullySubstituted) {
4133+
Pattern(Pattern), IndexExpr(IndexExpr), Size(Expansions.size()),
4134+
FullySubstituted(FullySubstituted) {
4135+
41364136
llvm::uninitialized_copy(Expansions, getTrailingObjects<QualType>());
41374137
}
41384138

@@ -4173,12 +4173,26 @@ PackIndexingType::computeDependence(QualType Pattern, Expr *IndexExpr,
41734173
return TD;
41744174
}
41754175

4176+
void PackIndexingType::Profile(llvm::FoldingSetNodeID &ID,
4177+
const ASTContext &Context) {
4178+
Profile(ID, Context, getPattern(), getIndexExpr(), isFullySubstituted(),
4179+
getExpansions());
4180+
}
4181+
41764182
void PackIndexingType::Profile(llvm::FoldingSetNodeID &ID,
41774183
const ASTContext &Context, QualType Pattern,
4178-
Expr *E, bool FullySubstituted) {
4179-
Pattern.Profile(ID);
4184+
Expr *E, bool FullySubstituted,
4185+
ArrayRef<QualType> Expansions) {
4186+
41804187
E->Profile(ID, Context, true);
41814188
ID.AddBoolean(FullySubstituted);
4189+
if (!Expansions.empty()) {
4190+
ID.AddInteger(Expansions.size());
4191+
for (QualType T : Expansions)
4192+
T.getCanonicalType().Profile(ID);
4193+
} else {
4194+
Pattern.Profile(ID);
4195+
}
41824196
}
41834197

41844198
UnaryTransformType::UnaryTransformType(QualType BaseType,

clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %clang_cc1 -std=c++20 -verify %s
1+
// RUN: %clang_cc1 -std=c++20 -Wno-c++26-extensions -verify %s
2+
// RUN: %clang_cc1 -std=c++2c -Wno-c++26-extensions -verify %s
3+
24

35
static constexpr int PRIMARY = 0;
46
static constexpr int SPECIALIZATION_CONCEPT = 1;
@@ -779,3 +781,75 @@ template <typename T>
779781
consteval void S::mfn() requires (bool(&fn)) {}
780782

781783
}
784+
785+
786+
namespace GH138255 {
787+
788+
template <typename... T>
789+
concept C = true;
790+
791+
struct Func {
792+
template<typename... Ts>
793+
requires C<Ts...[0]>
794+
static auto buggy() -> void;
795+
796+
template<typename... Ts>
797+
requires C<Ts...[0]>
798+
friend auto fr() -> void;
799+
800+
template<typename... Ts>
801+
requires C<Ts...[0]>
802+
friend auto fr2() -> void{}; // expected-note{{previous definition is here}}
803+
};
804+
805+
template<typename... Ts>
806+
requires C<Ts...[0]>
807+
auto Func::buggy() -> void {}
808+
809+
template<typename... Ts>
810+
requires C<Ts...[0]>
811+
auto fr() -> void {}
812+
813+
template<typename... Ts>
814+
requires C<Ts...[0]>
815+
auto fr2() -> void {} // expected-error{{redefinition of 'fr2'}}
816+
817+
818+
template <typename... Ts>
819+
requires C<Ts...[0]>
820+
struct Class;
821+
822+
template <typename... Ts>
823+
requires C<Ts...[0]>
824+
struct Class;
825+
826+
827+
template <typename...>
828+
struct TplClass {
829+
template<typename... Ts>
830+
requires C<Ts...[0]>
831+
static auto buggy() -> void;
832+
};
833+
834+
template<>
835+
template<typename... Ts>
836+
requires C<Ts...[0]>
837+
auto TplClass<int>::buggy() -> void {}
838+
839+
}
840+
841+
namespace PackIndexExpr {
842+
template <int... T>
843+
concept C = true;
844+
845+
template <typename...> struct TplClass {
846+
template <int... Ts>
847+
requires C<Ts...[0]>
848+
static auto buggy() -> void;
849+
};
850+
851+
template <>
852+
template <int... Ts>
853+
requires C<Ts...[0]>
854+
auto TplClass<int>::buggy() -> void {}
855+
}

0 commit comments

Comments
 (0)