1 //===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief This file provides AST data structures related to concepts.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_AST_ASTCONCEPT_H
16 #define LLVM_CLANG_AST_ASTCONCEPT_H
17 #include "clang/AST/Expr.h"
18 #include "clang/Basic/SourceLocation.h"
19 #include "llvm/ADT/PointerUnion.h"
20 #include "llvm/ADT/SmallVector.h"
25 class ConceptSpecializationExpr;
27 /// The result of a constraint satisfaction check, containing the necessary
28 /// information to diagnose an unsatisfied constraint.
29 class ConstraintSatisfaction : public llvm::FoldingSetNode {
30 // The template-like entity that 'owns' the constraint checked here (can be a
31 // constrained entity or a concept).
32 const NamedDecl *ConstraintOwner = nullptr;
33 llvm::SmallVector<TemplateArgument, 4> TemplateArgs;
37 ConstraintSatisfaction() = default;
39 ConstraintSatisfaction(const NamedDecl *ConstraintOwner,
40 ArrayRef<TemplateArgument> TemplateArgs) :
41 ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(),
42 TemplateArgs.end()) { }
44 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
45 using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
47 bool IsSatisfied = false;
49 /// \brief Pairs of unsatisfied atomic constraint expressions along with the
50 /// substituted constraint expr, if the template arguments could be
51 /// substituted into them, or a diagnostic if substitution resulted in an
52 /// invalid expression.
53 llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details;
55 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
56 Profile(ID, C, ConstraintOwner, TemplateArgs);
59 static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
60 const NamedDecl *ConstraintOwner,
61 ArrayRef<TemplateArgument> TemplateArgs);
64 /// Pairs of unsatisfied atomic constraint expressions along with the
65 /// substituted constraint expr, if the template arguments could be
66 /// substituted into them, or a diagnostic if substitution resulted in
67 /// an invalid expression.
68 using UnsatisfiedConstraintRecord =
69 std::pair<const Expr *,
70 llvm::PointerUnion<Expr *,
71 std::pair<SourceLocation, StringRef> *>>;
73 /// \brief The result of a constraint satisfaction check, containing the
74 /// necessary information to diagnose an unsatisfied constraint.
76 /// This is safe to store in an AST node, as opposed to ConstraintSatisfaction.
77 struct ASTConstraintSatisfaction final :
78 llvm::TrailingObjects<ASTConstraintSatisfaction,
79 UnsatisfiedConstraintRecord> {
80 std::size_t NumRecords;
83 const UnsatisfiedConstraintRecord *begin() const {
84 return getTrailingObjects<UnsatisfiedConstraintRecord>();
87 const UnsatisfiedConstraintRecord *end() const {
88 return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords;
91 ASTConstraintSatisfaction(const ASTContext &C,
92 const ConstraintSatisfaction &Satisfaction);
94 static ASTConstraintSatisfaction *
95 Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
98 /// \brief Common data class for constructs that reference concepts with
99 /// template arguments.
100 class ConceptReference {
102 // \brief The optional nested name specifier used when naming the concept.
103 NestedNameSpecifierLoc NestedNameSpec;
105 /// \brief The location of the template keyword, if specified when naming the
107 SourceLocation TemplateKWLoc;
109 /// \brief The concept name used.
110 DeclarationNameInfo ConceptName;
112 /// \brief The declaration found by name lookup when the expression was
114 /// Can differ from NamedConcept when, for example, the concept was found
115 /// through a UsingShadowDecl.
116 NamedDecl *FoundDecl;
118 /// \brief The concept named.
119 ConceptDecl *NamedConcept;
121 /// \brief The template argument list source info used to specialize the
123 const ASTTemplateArgumentListInfo *ArgsAsWritten;
127 ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
128 DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
129 ConceptDecl *NamedConcept,
130 const ASTTemplateArgumentListInfo *ArgsAsWritten) :
131 NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
132 ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
133 NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {}
135 ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(),
136 FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {}
138 const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
139 return NestedNameSpec;
142 const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; }
144 SourceLocation getConceptNameLoc() const {
145 return getConceptNameInfo().getLoc();
148 SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
150 NamedDecl *getFoundDecl() const {
154 ConceptDecl *getNamedConcept() const {
158 const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
159 return ArgsAsWritten;
162 /// \brief Whether or not template arguments were explicitly specified in the
163 /// concept reference (they might not be in type constraints, for example)
164 bool hasExplicitTemplateArgs() const {
165 return ArgsAsWritten != nullptr;
169 class TypeConstraint : public ConceptReference {
170 /// \brief The immediately-declared constraint expression introduced by this
172 Expr *ImmediatelyDeclaredConstraint = nullptr;
175 TypeConstraint(NestedNameSpecifierLoc NNS,
176 DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
177 ConceptDecl *NamedConcept,
178 const ASTTemplateArgumentListInfo *ArgsAsWritten,
179 Expr *ImmediatelyDeclaredConstraint) :
180 ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo,
181 FoundDecl, NamedConcept, ArgsAsWritten),
182 ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {}
184 /// \brief Get the immediately-declared constraint expression introduced by
185 /// this type-constraint, that is - the constraint expression that is added to
186 /// the associated constraints of the enclosing declaration in practice.
187 Expr *getImmediatelyDeclaredConstraint() const {
188 return ImmediatelyDeclaredConstraint;
191 void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const;
196 #endif // LLVM_CLANG_AST_ASTCONCEPT_H