Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | /// |
||
9 | /// \file |
||
10 | /// \brief This file provides AST data structures related to concepts. |
||
11 | /// |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_CLANG_AST_ASTCONCEPT_H |
||
15 | #define LLVM_CLANG_AST_ASTCONCEPT_H |
||
16 | |||
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 <utility> |
||
22 | |||
23 | namespace clang { |
||
24 | class ConceptDecl; |
||
25 | |||
26 | /// The result of a constraint satisfaction check, containing the necessary |
||
27 | /// information to diagnose an unsatisfied constraint. |
||
28 | class ConstraintSatisfaction : public llvm::FoldingSetNode { |
||
29 | // The template-like entity that 'owns' the constraint checked here (can be a |
||
30 | // constrained entity or a concept). |
||
31 | const NamedDecl *ConstraintOwner = nullptr; |
||
32 | llvm::SmallVector<TemplateArgument, 4> TemplateArgs; |
||
33 | |||
34 | public: |
||
35 | |||
36 | ConstraintSatisfaction() = default; |
||
37 | |||
38 | ConstraintSatisfaction(const NamedDecl *ConstraintOwner, |
||
39 | ArrayRef<TemplateArgument> TemplateArgs) : |
||
40 | ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(), |
||
41 | TemplateArgs.end()) { } |
||
42 | |||
43 | using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; |
||
44 | using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>; |
||
45 | |||
46 | bool IsSatisfied = false; |
||
47 | bool ContainsErrors = 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 | bool HasSubstitutionFailure() { |
||
64 | for (const auto &Detail : Details) |
||
65 | if (Detail.second.dyn_cast<SubstitutionDiagnostic *>()) |
||
66 | return true; |
||
67 | return false; |
||
68 | } |
||
69 | }; |
||
70 | |||
71 | /// Pairs of unsatisfied atomic constraint expressions along with the |
||
72 | /// substituted constraint expr, if the template arguments could be |
||
73 | /// substituted into them, or a diagnostic if substitution resulted in |
||
74 | /// an invalid expression. |
||
75 | using UnsatisfiedConstraintRecord = |
||
76 | std::pair<const Expr *, |
||
77 | llvm::PointerUnion<Expr *, |
||
78 | std::pair<SourceLocation, StringRef> *>>; |
||
79 | |||
80 | /// \brief The result of a constraint satisfaction check, containing the |
||
81 | /// necessary information to diagnose an unsatisfied constraint. |
||
82 | /// |
||
83 | /// This is safe to store in an AST node, as opposed to ConstraintSatisfaction. |
||
84 | struct ASTConstraintSatisfaction final : |
||
85 | llvm::TrailingObjects<ASTConstraintSatisfaction, |
||
86 | UnsatisfiedConstraintRecord> { |
||
87 | std::size_t NumRecords; |
||
88 | bool IsSatisfied : 1; |
||
89 | bool ContainsErrors : 1; |
||
90 | |||
91 | const UnsatisfiedConstraintRecord *begin() const { |
||
92 | return getTrailingObjects<UnsatisfiedConstraintRecord>(); |
||
93 | } |
||
94 | |||
95 | const UnsatisfiedConstraintRecord *end() const { |
||
96 | return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords; |
||
97 | } |
||
98 | |||
99 | ASTConstraintSatisfaction(const ASTContext &C, |
||
100 | const ConstraintSatisfaction &Satisfaction); |
||
101 | ASTConstraintSatisfaction(const ASTContext &C, |
||
102 | const ASTConstraintSatisfaction &Satisfaction); |
||
103 | |||
104 | static ASTConstraintSatisfaction * |
||
105 | Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction); |
||
106 | static ASTConstraintSatisfaction * |
||
107 | Rebuild(const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction); |
||
108 | }; |
||
109 | |||
110 | /// \brief Common data class for constructs that reference concepts with |
||
111 | /// template arguments. |
||
112 | class ConceptReference { |
||
113 | protected: |
||
114 | // \brief The optional nested name specifier used when naming the concept. |
||
115 | NestedNameSpecifierLoc NestedNameSpec; |
||
116 | |||
117 | /// \brief The location of the template keyword, if specified when naming the |
||
118 | /// concept. |
||
119 | SourceLocation TemplateKWLoc; |
||
120 | |||
121 | /// \brief The concept name used. |
||
122 | DeclarationNameInfo ConceptName; |
||
123 | |||
124 | /// \brief The declaration found by name lookup when the expression was |
||
125 | /// created. |
||
126 | /// Can differ from NamedConcept when, for example, the concept was found |
||
127 | /// through a UsingShadowDecl. |
||
128 | NamedDecl *FoundDecl; |
||
129 | |||
130 | /// \brief The concept named. |
||
131 | ConceptDecl *NamedConcept; |
||
132 | |||
133 | /// \brief The template argument list source info used to specialize the |
||
134 | /// concept. |
||
135 | const ASTTemplateArgumentListInfo *ArgsAsWritten; |
||
136 | |||
137 | public: |
||
138 | ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, |
||
139 | DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, |
||
140 | ConceptDecl *NamedConcept, |
||
141 | const ASTTemplateArgumentListInfo *ArgsAsWritten) |
||
142 | : NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), |
||
143 | ConceptName(ConceptNameInfo), FoundDecl(FoundDecl), |
||
144 | NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {} |
||
145 | |||
146 | ConceptReference() |
||
147 | : FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {} |
||
148 | |||
149 | const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { |
||
150 | return NestedNameSpec; |
||
151 | } |
||
152 | |||
153 | const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; } |
||
154 | |||
155 | SourceLocation getConceptNameLoc() const { |
||
156 | return getConceptNameInfo().getLoc(); |
||
157 | } |
||
158 | |||
159 | SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; } |
||
160 | |||
161 | NamedDecl *getFoundDecl() const { |
||
162 | return FoundDecl; |
||
163 | } |
||
164 | |||
165 | ConceptDecl *getNamedConcept() const { |
||
166 | return NamedConcept; |
||
167 | } |
||
168 | |||
169 | const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { |
||
170 | return ArgsAsWritten; |
||
171 | } |
||
172 | |||
173 | /// \brief Whether or not template arguments were explicitly specified in the |
||
174 | /// concept reference (they might not be in type constraints, for example) |
||
175 | bool hasExplicitTemplateArgs() const { |
||
176 | return ArgsAsWritten != nullptr; |
||
177 | } |
||
178 | }; |
||
179 | |||
180 | class TypeConstraint : public ConceptReference { |
||
181 | /// \brief The immediately-declared constraint expression introduced by this |
||
182 | /// type-constraint. |
||
183 | Expr *ImmediatelyDeclaredConstraint = nullptr; |
||
184 | |||
185 | public: |
||
186 | TypeConstraint(NestedNameSpecifierLoc NNS, |
||
187 | DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, |
||
188 | ConceptDecl *NamedConcept, |
||
189 | const ASTTemplateArgumentListInfo *ArgsAsWritten, |
||
190 | Expr *ImmediatelyDeclaredConstraint) : |
||
191 | ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo, |
||
192 | FoundDecl, NamedConcept, ArgsAsWritten), |
||
193 | ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {} |
||
194 | |||
195 | /// \brief Get the immediately-declared constraint expression introduced by |
||
196 | /// this type-constraint, that is - the constraint expression that is added to |
||
197 | /// the associated constraints of the enclosing declaration in practice. |
||
198 | Expr *getImmediatelyDeclaredConstraint() const { |
||
199 | return ImmediatelyDeclaredConstraint; |
||
200 | } |
||
201 | |||
202 | void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const; |
||
203 | }; |
||
204 | |||
205 | } // clang |
||
206 | |||
207 | #endif // LLVM_CLANG_AST_ASTCONCEPT_H |