Skip to content

Commit ff1e0fc

Browse files
committed
[Concepts] Type Constraints
Add support for type-constraints in template type parameters. Also add support for template type parameters as pack expansions (where the type constraint can now contain an unexpanded parameter pack). Differential Revision: https://reviews.llvm.org/D44352
1 parent 8e78025 commit ff1e0fc

40 files changed

+1566
-315
lines changed

clang/include/clang/AST/ASTConcept.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <string>
2222
#include <utility>
2323
namespace clang {
24+
class ConceptDecl;
2425

2526
/// \brief The result of a constraint satisfaction check, containing the
2627
/// necessary information to diagnose an unsatisfied constraint.
@@ -75,6 +76,102 @@ struct ASTConstraintSatisfaction final :
7576
Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
7677
};
7778

79+
/// \brief Common data class for constructs that reference concepts with
80+
/// template arguments.
81+
class ConceptReference {
82+
protected:
83+
// \brief The optional nested name specifier used when naming the concept.
84+
NestedNameSpecifierLoc NestedNameSpec;
85+
86+
/// \brief The ___location of the template keyword, if specified when naming the
87+
/// concept.
88+
SourceLocation TemplateKWLoc;
89+
90+
/// \brief The concept name used.
91+
DeclarationNameInfo ConceptName;
92+
93+
/// \brief The declaration found by name lookup when the expression was
94+
/// created.
95+
/// Can differ from NamedConcept when, for example, the concept was found
96+
/// through a UsingShadowDecl.
97+
NamedDecl *FoundDecl;
98+
99+
/// \brief The concept named.
100+
ConceptDecl *NamedConcept;
101+
102+
/// \brief The template argument list source info used to specialize the
103+
/// concept.
104+
const ASTTemplateArgumentListInfo *ArgsAsWritten;
105+
106+
public:
107+
108+
ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
109+
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
110+
ConceptDecl *NamedConcept,
111+
const ASTTemplateArgumentListInfo *ArgsAsWritten) :
112+
NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
113+
ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
114+
NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {}
115+
116+
ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(),
117+
FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {}
118+
119+
const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
120+
return NestedNameSpec;
121+
}
122+
123+
const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; }
124+
125+
SourceLocation getConceptNameLoc() const {
126+
return getConceptNameInfo().getLoc();
127+
}
128+
129+
SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
130+
131+
NamedDecl *getFoundDecl() const {
132+
return FoundDecl;
133+
}
134+
135+
ConceptDecl *getNamedConcept() const {
136+
return NamedConcept;
137+
}
138+
139+
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
140+
return ArgsAsWritten;
141+
}
142+
143+
/// \brief Whether or not template arguments were explicitly specified in the
144+
/// concept reference (they might not be in type constraints, for example)
145+
bool hasExplicitTemplateArgs() const {
146+
return ArgsAsWritten != nullptr;
147+
}
148+
};
149+
150+
class TypeConstraint : public ConceptReference {
151+
/// \brief The immediately-declared constraint expression introduced by this
152+
/// type-constraint.
153+
Expr *ImmediatelyDeclaredConstraint = nullptr;
154+
155+
public:
156+
TypeConstraint(NestedNameSpecifierLoc NNS,
157+
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
158+
ConceptDecl *NamedConcept,
159+
const ASTTemplateArgumentListInfo *ArgsAsWritten,
160+
Expr *ImmediatelyDeclaredConstraint) :
161+
ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo,
162+
FoundDecl, NamedConcept, ArgsAsWritten),
163+
ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {}
164+
165+
/// \brief Get the immediately-declared constraint expression introduced by
166+
/// this type-constraint, that is - the constraint expression that is added to
167+
/// the associated constraints of the enclosing declaration in practice.
168+
Expr *getImmediatelyDeclaredConstraint() const {
169+
return ImmediatelyDeclaredConstraint;
170+
}
171+
172+
void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const;
173+
};
174+
78175
} // clang
79176

80177
#endif // LLVM_CLANG_AST_ASTCONCEPT_H

clang/include/clang/AST/ASTContext.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
283283

284284
TemplateTemplateParmDecl *getParam() const { return Parm; }
285285

286-
void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); }
286+
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
287+
Profile(ID, C, Parm);
288+
}
287289

288290
static void Profile(llvm::FoldingSetNodeID &ID,
291+
const ASTContext &C,
289292
TemplateTemplateParmDecl *Parm);
290293
};
291-
mutable llvm::FoldingSet<CanonicalTemplateTemplateParm>
294+
mutable llvm::ContextualFoldingSet<CanonicalTemplateTemplateParm,
295+
const ASTContext&>
292296
CanonTemplateTemplateParms;
293297

294298
TemplateTemplateParmDecl *

clang/include/clang/AST/ASTNodeTraverser.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,13 +537,19 @@ class ASTNodeTraverser
537537
}
538538

539539
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
540+
if (const auto *TC = D->getTypeConstraint())
541+
if (TC->hasExplicitTemplateArgs())
542+
for (const auto &ArgLoc : TC->getTemplateArgsAsWritten()->arguments())
543+
dumpTemplateArgumentLoc(ArgLoc);
540544
if (D->hasDefaultArgument())
541545
Visit(D->getDefaultArgument(), SourceRange(),
542546
D->getDefaultArgStorage().getInheritedFrom(),
543547
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
544548
}
545549

546550
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
551+
if (const auto *TC = D->getPlaceholderTypeConstraint())
552+
Visit(TC->getImmediatelyDeclaredConstraint());
547553
if (D->hasDefaultArgument())
548554
Visit(D->getDefaultArgument(), SourceRange(),
549555
D->getDefaultArgStorage().getInheritedFrom(),

0 commit comments

Comments
 (0)