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 |