Skip to content

Commit 975740b

Browse files
author
Erich Keane
committed
"Reapply "GH58368: Correct concept checking in a lambda defined in concept""
This reverts commit cecc9a9. The problem ended up being how we were handling the lambda-context in code generation: we were assuming any decl context here would be a named-decl, but that isn't the case. Instead, we just replace it with the concept's owning context. Differential Revision: https://reviews.llvm.org/D136451
1 parent 18066b5 commit 975740b

26 files changed

+268
-102
lines changed

clang/include/clang/AST/ASTNodeTraverser.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,14 @@ class ASTNodeTraverser
623623
Visit(D->getConstraintExpr());
624624
}
625625

626+
void VisitImplicitConceptSpecializationDecl(
627+
const ImplicitConceptSpecializationDecl *CSD) {
628+
for (const TemplateArgument &Arg : CSD->getTemplateArguments())
629+
Visit(Arg);
630+
}
631+
626632
void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *CSE) {
633+
Visit(CSE->getSpecializationDecl());
627634
if (CSE->hasExplicitTemplateArgs())
628635
for (const auto &ArgLoc : CSE->getTemplateArgsAsWritten()->arguments())
629636
dumpTemplateArgumentLoc(ArgLoc);

clang/include/clang/AST/DeclTemplate.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3259,7 +3259,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
32593259
static bool classofKind(Kind K) { return K == VarTemplate; }
32603260
};
32613261

3262-
/// Declaration of a C++2a concept.
3262+
/// Declaration of a C++20 concept.
32633263
class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
32643264
protected:
32653265
Expr *ConstraintExpr;
@@ -3304,6 +3304,40 @@ class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
33043304
friend class ASTDeclWriter;
33053305
};
33063306

3307+
// An implementation detail of ConceptSpecialicationExpr that holds the template
3308+
// arguments, so we can later use this to reconstitute the template arguments
3309+
// during constraint checking.
3310+
class ImplicitConceptSpecializationDecl final
3311+
: public Decl,
3312+
private llvm::TrailingObjects<ImplicitConceptSpecializationDecl,
3313+
TemplateArgument> {
3314+
unsigned NumTemplateArgs;
3315+
3316+
ImplicitConceptSpecializationDecl(DeclContext *DC, SourceLocation SL,
3317+
ArrayRef<TemplateArgument> ConvertedArgs);
3318+
ImplicitConceptSpecializationDecl(EmptyShell Empty, unsigned NumTemplateArgs);
3319+
3320+
public:
3321+
static ImplicitConceptSpecializationDecl *
3322+
Create(const ASTContext &C, DeclContext *DC, SourceLocation SL,
3323+
ArrayRef<TemplateArgument> ConvertedArgs);
3324+
static ImplicitConceptSpecializationDecl *
3325+
CreateDeserialized(const ASTContext &C, unsigned ID,
3326+
unsigned NumTemplateArgs);
3327+
3328+
ArrayRef<TemplateArgument> getTemplateArguments() const {
3329+
return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
3330+
NumTemplateArgs);
3331+
}
3332+
void setTemplateArguments(ArrayRef<TemplateArgument> Converted);
3333+
3334+
static bool classofKind(Kind K) { return K == ImplicitConceptSpecialization; }
3335+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
3336+
3337+
friend TrailingObjects;
3338+
friend class ASTDeclReader;
3339+
};
3340+
33073341
/// A template parameter object.
33083342
///
33093343
/// Template parameter objects represent values of class type used as template

clang/include/clang/AST/ExprConcepts.h

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,17 @@ class ASTStmtWriter;
3737
///
3838
/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the
3939
/// specialization of a concept results in a prvalue of type bool.
40-
class ConceptSpecializationExpr final : public Expr, public ConceptReference,
41-
private llvm::TrailingObjects<ConceptSpecializationExpr,
42-
TemplateArgument> {
40+
class ConceptSpecializationExpr final : public Expr, public ConceptReference {
41+
friend class ASTReader;
4342
friend class ASTStmtReader;
44-
friend TrailingObjects;
43+
4544
public:
4645
using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
4746

4847
protected:
49-
/// \brief The number of template arguments in the tail-allocated list of
50-
/// converted template arguments.
51-
unsigned NumTemplateArgs;
48+
/// \brief The Implicit Concept Specialization Decl, which holds the template
49+
/// arguments for this specialization.
50+
ImplicitConceptSpecializationDecl *SpecDecl;
5251

5352
/// \brief Information about the satisfaction of the named concept with the
5453
/// given arguments. If this expression is value dependent, this is to be
@@ -60,60 +59,55 @@ class ConceptSpecializationExpr final : public Expr, public ConceptReference,
6059
DeclarationNameInfo ConceptNameInfo,
6160
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
6261
const ASTTemplateArgumentListInfo *ArgsAsWritten,
63-
ArrayRef<TemplateArgument> ConvertedArgs,
62+
ImplicitConceptSpecializationDecl *SpecDecl,
6463
const ConstraintSatisfaction *Satisfaction);
6564

6665
ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
67-
ArrayRef<TemplateArgument> ConvertedArgs,
66+
ImplicitConceptSpecializationDecl *SpecDecl,
6867
const ConstraintSatisfaction *Satisfaction,
6968
bool Dependent,
7069
bool ContainsUnexpandedParameterPack);
71-
72-
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
70+
ConceptSpecializationExpr(EmptyShell Empty);
7371

7472
public:
75-
7673
static ConceptSpecializationExpr *
7774
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
7875
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
7976
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
8077
const ASTTemplateArgumentListInfo *ArgsAsWritten,
81-
ArrayRef<TemplateArgument> ConvertedArgs,
78+
ImplicitConceptSpecializationDecl *SpecDecl,
8279
const ConstraintSatisfaction *Satisfaction);
8380

8481
static ConceptSpecializationExpr *
8582
Create(const ASTContext &C, ConceptDecl *NamedConcept,
86-
ArrayRef<TemplateArgument> ConvertedArgs,
87-
const ConstraintSatisfaction *Satisfaction,
88-
bool Dependent,
83+
ImplicitConceptSpecializationDecl *SpecDecl,
84+
const ConstraintSatisfaction *Satisfaction, bool Dependent,
8985
bool ContainsUnexpandedParameterPack);
9086

91-
static ConceptSpecializationExpr *
92-
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
93-
9487
ArrayRef<TemplateArgument> getTemplateArguments() const {
95-
return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
96-
NumTemplateArgs);
88+
return SpecDecl->getTemplateArguments();
9789
}
9890

99-
/// \brief Set new template arguments for this concept specialization.
100-
void setTemplateArguments(ArrayRef<TemplateArgument> Converted);
91+
const ImplicitConceptSpecializationDecl *getSpecializationDecl() const {
92+
assert(SpecDecl && "Template Argument Decl not initialized");
93+
return SpecDecl;
94+
}
10195

10296
/// \brief Whether or not the concept with the given arguments was satisfied
10397
/// when the expression was created.
10498
/// The expression must not be dependent.
10599
bool isSatisfied() const {
106-
assert(!isValueDependent()
107-
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
100+
assert(!isValueDependent() &&
101+
"isSatisfied called on a dependent ConceptSpecializationExpr");
108102
return Satisfaction->IsSatisfied;
109103
}
110104

111105
/// \brief Get elaborated satisfaction info about the template arguments'
112106
/// satisfaction of the named concept.
113107
/// The expression must not be dependent.
114108
const ASTConstraintSatisfaction &getSatisfaction() const {
115-
assert(!isValueDependent()
116-
&& "getSatisfaction called on dependent ConceptSpecializationExpr");
109+
assert(!isValueDependent() &&
110+
"getSatisfaction called on dependent ConceptSpecializationExpr");
117111
return *Satisfaction;
118112
}
119113

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2304,6 +2304,11 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
23042304

23052305
DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {})
23062306

2307+
DEF_TRAVERSE_DECL(ImplicitConceptSpecializationDecl, {
2308+
TRY_TO(TraverseTemplateArguments(D->getTemplateArguments().data(),
2309+
D->getTemplateArguments().size()));
2310+
})
2311+
23072312
#undef DEF_TRAVERSE_DECL
23082313

23092314
// ----------------- Stmt traversal -----------------

clang/include/clang/Basic/DeclNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def Named : DeclNode<Decl, "named declarations", 1>;
9090
def ObjCImplementation : DeclNode<ObjCImpl>;
9191
def ObjCProperty : DeclNode<Named, "Objective-C properties">;
9292
def ObjCCompatibleAlias : DeclNode<Named>;
93+
def ImplicitConceptSpecialization : DeclNode<Decl>;
9394
def LinkageSpec : DeclNode<Decl>, DeclContext;
9495
def Export : DeclNode<Decl>, DeclContext;
9596
def ObjCPropertyImpl : DeclNode<Decl>;

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ namespace serialization {
4141
/// Version 4 of AST files also requires that the version control branch and
4242
/// revision match exactly, since there is no backward compatibility of
4343
/// AST files at this time.
44-
const unsigned VERSION_MAJOR = 22;
44+
const unsigned VERSION_MAJOR = 23;
4545

4646
/// AST file minor version number supported by this version of
4747
/// Clang.
@@ -1514,7 +1514,10 @@ enum DeclCode {
15141514
/// A HLSLBufferDecl record.
15151515
DECL_HLSL_BUFFER,
15161516

1517-
DECL_LAST = DECL_HLSL_BUFFER
1517+
/// An ImplicitConceptSpecializationDecl record.
1518+
DECL_IMPLICIT_CONCEPT_SPECIALIZATION,
1519+
1520+
DECL_LAST = DECL_IMPLICIT_CONCEPT_SPECIALIZATION
15181521
};
15191522

15201523
/// Record codes for each kind of statement or expression.

clang/lib/AST/ASTContext.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,9 +761,13 @@ canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC,
761761
NewConverted.push_back(ConstrainedType);
762762
llvm::append_range(NewConverted, OldConverted.drop_front(1));
763763
}
764+
auto *CSD = ImplicitConceptSpecializationDecl::Create(
765+
C, CSE->getNamedConcept()->getDeclContext(),
766+
CSE->getNamedConcept()->getLocation(), NewConverted);
767+
764768
Expr *NewIDC = ConceptSpecializationExpr::Create(
765-
C, CSE->getNamedConcept(), NewConverted, nullptr,
766-
CSE->isInstantiationDependent(), CSE->containsUnexpandedParameterPack());
769+
C, CSE->getNamedConcept(), CSD, nullptr, CSE->isInstantiationDependent(),
770+
CSE->containsUnexpandedParameterPack());
767771

768772
if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC))
769773
NewIDC = new (C) CXXFoldExpr(

clang/lib/AST/Decl.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,8 +1262,13 @@ LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
12621262
else if (isa<ParmVarDecl>(ContextDecl))
12631263
Owner =
12641264
dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext());
1265-
else
1265+
else if (isa<ImplicitConceptSpecializationDecl>(ContextDecl)) {
1266+
// Replace with the concept's owning decl, which is either a namespace or a
1267+
// TU, so this needs a dyn_cast.
1268+
Owner = dyn_cast<NamedDecl>(ContextDecl->getDeclContext());
1269+
} else {
12661270
Owner = cast<NamedDecl>(ContextDecl);
1271+
}
12671272

12681273
if (!Owner)
12691274
return LinkageInfo::none();

clang/lib/AST/DeclBase.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
874874
case Empty:
875875
case LifetimeExtendedTemporary:
876876
case RequiresExprBody:
877+
case ImplicitConceptSpecialization:
877878
// Never looked up by name.
878879
return 0;
879880
}

clang/lib/AST/DeclTemplate.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,44 @@ ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C,
10521052
return Result;
10531053
}
10541054

1055+
//===----------------------------------------------------------------------===//
1056+
// ImplicitConceptSpecializationDecl Implementation
1057+
//===----------------------------------------------------------------------===//
1058+
ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
1059+
DeclContext *DC, SourceLocation SL,
1060+
ArrayRef<TemplateArgument> ConvertedArgs)
1061+
: Decl(ImplicitConceptSpecialization, DC, SL),
1062+
NumTemplateArgs(ConvertedArgs.size()) {
1063+
setTemplateArguments(ConvertedArgs);
1064+
}
1065+
1066+
ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
1067+
EmptyShell Empty, unsigned NumTemplateArgs)
1068+
: Decl(ImplicitConceptSpecialization, Empty),
1069+
NumTemplateArgs(NumTemplateArgs) {}
1070+
1071+
ImplicitConceptSpecializationDecl *ImplicitConceptSpecializationDecl::Create(
1072+
const ASTContext &C, DeclContext *DC, SourceLocation SL,
1073+
ArrayRef<TemplateArgument> ConvertedArgs) {
1074+
return new (C, DC,
1075+
additionalSizeToAlloc<TemplateArgument>(ConvertedArgs.size()))
1076+
ImplicitConceptSpecializationDecl(DC, SL, ConvertedArgs);
1077+
}
1078+
1079+
ImplicitConceptSpecializationDecl *
1080+
ImplicitConceptSpecializationDecl::CreateDeserialized(
1081+
const ASTContext &C, unsigned ID, unsigned NumTemplateArgs) {
1082+
return new (C, ID, additionalSizeToAlloc<TemplateArgument>(NumTemplateArgs))
1083+
ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs);
1084+
}
1085+
1086+
void ImplicitConceptSpecializationDecl::setTemplateArguments(
1087+
ArrayRef<TemplateArgument> Converted) {
1088+
assert(Converted.size() == NumTemplateArgs);
1089+
std::uninitialized_copy(Converted.begin(), Converted.end(),
1090+
getTrailingObjects<TemplateArgument>());
1091+
}
1092+
10551093
//===----------------------------------------------------------------------===//
10561094
// ClassTemplatePartialSpecializationDecl Implementation
10571095
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)