1//===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file provides AST data structures related to concepts.
12///
13//===----------------------------------------------------------------------===//
14
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"
21#include <string>
22#include <utility>
23namespace clang {
24class ConceptDecl;
25class ConceptSpecializationExpr;
26
27/// The result of a constraint satisfaction check, containing the necessary
28/// information to diagnose an unsatisfied constraint.
29class 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;
34
35public:
36
37 ConstraintSatisfaction() = default;
38
39 ConstraintSatisfaction(const NamedDecl *ConstraintOwner,
40 ArrayRef<TemplateArgument> TemplateArgs) :
41 ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(),
42 TemplateArgs.end()) { }
43
44 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
45 using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
46
47 bool IsSatisfied = false;
48
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;
54
55 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
56 Profile(ID, C, ConstraintOwner, TemplateArgs);
57 }
58
59 static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
60 const NamedDecl *ConstraintOwner,
61 ArrayRef<TemplateArgument> TemplateArgs);
62};
63
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.
68using UnsatisfiedConstraintRecord =
69 std::pair<const Expr *,
70 llvm::PointerUnion<Expr *,
71 std::pair<SourceLocation, StringRef> *>>;
72
73/// \brief The result of a constraint satisfaction check, containing the
74/// necessary information to diagnose an unsatisfied constraint.
75///
76/// This is safe to store in an AST node, as opposed to ConstraintSatisfaction.
77struct ASTConstraintSatisfaction final :
78 llvm::TrailingObjects<ASTConstraintSatisfaction,
79 UnsatisfiedConstraintRecord> {
80 std::size_t NumRecords;
81 bool IsSatisfied : 1;
82
83 const UnsatisfiedConstraintRecord *begin() const {
84 return getTrailingObjects<UnsatisfiedConstraintRecord>();
85 }
86
87 const UnsatisfiedConstraintRecord *end() const {
88 return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords;
89 }
90
91 ASTConstraintSatisfaction(const ASTContext &C,
92 const ConstraintSatisfaction &Satisfaction);
93
94 static ASTConstraintSatisfaction *
95 Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
96};
97
98/// \brief Common data class for constructs that reference concepts with
99/// template arguments.
100class ConceptReference {
101protected:
102 // \brief The optional nested name specifier used when naming the concept.
103 NestedNameSpecifierLoc NestedNameSpec;
104
105 /// \brief The location of the template keyword, if specified when naming the
106 /// concept.
107 SourceLocation TemplateKWLoc;
108
109 /// \brief The concept name used.
110 DeclarationNameInfo ConceptName;
111
112 /// \brief The declaration found by name lookup when the expression was
113 /// created.
114 /// Can differ from NamedConcept when, for example, the concept was found
115 /// through a UsingShadowDecl.
116 NamedDecl *FoundDecl;
117
118 /// \brief The concept named.
119 ConceptDecl *NamedConcept;
120
121 /// \brief The template argument list source info used to specialize the
122 /// concept.
123 const ASTTemplateArgumentListInfo *ArgsAsWritten;
124
125public:
126
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) {}
134
135 ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(),
136 FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {}
137
138 const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
139 return NestedNameSpec;
140 }
141
142 const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; }
143
144 SourceLocation getConceptNameLoc() const {
145 return getConceptNameInfo().getLoc();
146 }
147
148 SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
149
150 NamedDecl *getFoundDecl() const {
151 return FoundDecl;
152 }
153
154 ConceptDecl *getNamedConcept() const {
155 return NamedConcept;
156 }
157
158 const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
159 return ArgsAsWritten;
160 }
161
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;
166 }
167};
168
169class TypeConstraint : public ConceptReference {
170 /// \brief The immediately-declared constraint expression introduced by this
171 /// type-constraint.
172 Expr *ImmediatelyDeclaredConstraint = nullptr;
173
174public:
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) {}
183
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;
189 }
190
191 void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const;
192};
193
194} // clang
195
196#endif // LLVM_CLANG_AST_ASTCONCEPT_H
197