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 18 #include "clang/AST/Expr.h" 19 #include "clang/Basic/SourceLocation.h" 20 #include "llvm/ADT/PointerUnion.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include <utility> 23 24 namespace clang { 25 class ConceptDecl; 26 class ConceptSpecializationExpr; 27 28 /// The result of a constraint satisfaction check, containing the necessary 29 /// information to diagnose an unsatisfied constraint. 30 class ConstraintSatisfaction : public llvm::FoldingSetNode { 31 // The template-like entity that 'owns' the constraint checked here (can be a 32 // constrained entity or a concept). 33 const NamedDecl *ConstraintOwner = nullptr; 34 llvm::SmallVector<TemplateArgument, 4> TemplateArgs; 35 36 public: 37 38 ConstraintSatisfaction() = default; 39 40 ConstraintSatisfaction(const NamedDecl *ConstraintOwner, 41 ArrayRef<TemplateArgument> TemplateArgs) : 42 ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(), 43 TemplateArgs.end()) { } 44 45 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; 46 using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>; 47 48 bool IsSatisfied = false; 49 50 /// \brief Pairs of unsatisfied atomic constraint expressions along with the 51 /// substituted constraint expr, if the template arguments could be 52 /// substituted into them, or a diagnostic if substitution resulted in an 53 /// invalid expression. 54 llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details; 55 56 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) { 57 Profile(ID, C, ConstraintOwner, TemplateArgs); 58 } 59 60 static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C, 61 const NamedDecl *ConstraintOwner, 62 ArrayRef<TemplateArgument> TemplateArgs); 63 }; 64 65 /// Pairs of unsatisfied atomic constraint expressions along with the 66 /// substituted constraint expr, if the template arguments could be 67 /// substituted into them, or a diagnostic if substitution resulted in 68 /// an invalid expression. 69 using UnsatisfiedConstraintRecord = 70 std::pair<const Expr *, 71 llvm::PointerUnion<Expr *, 72 std::pair<SourceLocation, StringRef> *>>; 73 74 /// \brief The result of a constraint satisfaction check, containing the 75 /// necessary information to diagnose an unsatisfied constraint. 76 /// 77 /// This is safe to store in an AST node, as opposed to ConstraintSatisfaction. 78 struct ASTConstraintSatisfaction final : 79 llvm::TrailingObjects<ASTConstraintSatisfaction, 80 UnsatisfiedConstraintRecord> { 81 std::size_t NumRecords; 82 bool IsSatisfied : 1; 83 84 const UnsatisfiedConstraintRecord *begin() const { 85 return getTrailingObjects<UnsatisfiedConstraintRecord>(); 86 } 87 88 const UnsatisfiedConstraintRecord *end() const { 89 return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords; 90 } 91 92 ASTConstraintSatisfaction(const ASTContext &C, 93 const ConstraintSatisfaction &Satisfaction); 94 95 static ASTConstraintSatisfaction * 96 Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction); 97 }; 98 99 /// \brief Common data class for constructs that reference concepts with 100 /// template arguments. 101 class ConceptReference { 102 protected: 103 // \brief The optional nested name specifier used when naming the concept. 104 NestedNameSpecifierLoc NestedNameSpec; 105 106 /// \brief The location of the template keyword, if specified when naming the 107 /// concept. 108 SourceLocation TemplateKWLoc; 109 110 /// \brief The concept name used. 111 DeclarationNameInfo ConceptName; 112 113 /// \brief The declaration found by name lookup when the expression was 114 /// created. 115 /// Can differ from NamedConcept when, for example, the concept was found 116 /// through a UsingShadowDecl. 117 NamedDecl *FoundDecl; 118 119 /// \brief The concept named. 120 ConceptDecl *NamedConcept; 121 122 /// \brief The template argument list source info used to specialize the 123 /// concept. 124 const ASTTemplateArgumentListInfo *ArgsAsWritten; 125 126 public: 127 128 ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, 129 DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, 130 ConceptDecl *NamedConcept, 131 const ASTTemplateArgumentListInfo *ArgsAsWritten) : 132 NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), 133 ConceptName(ConceptNameInfo), FoundDecl(FoundDecl), 134 NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {} 135 136 ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(), 137 FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {} 138 139 const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { 140 return NestedNameSpec; 141 } 142 143 const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; } 144 145 SourceLocation getConceptNameLoc() const { 146 return getConceptNameInfo().getLoc(); 147 } 148 149 SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; } 150 151 NamedDecl *getFoundDecl() const { 152 return FoundDecl; 153 } 154 155 ConceptDecl *getNamedConcept() const { 156 return NamedConcept; 157 } 158 159 const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { 160 return ArgsAsWritten; 161 } 162 163 /// \brief Whether or not template arguments were explicitly specified in the 164 /// concept reference (they might not be in type constraints, for example) 165 bool hasExplicitTemplateArgs() const { 166 return ArgsAsWritten != nullptr; 167 } 168 }; 169 170 class TypeConstraint : public ConceptReference { 171 /// \brief The immediately-declared constraint expression introduced by this 172 /// type-constraint. 173 Expr *ImmediatelyDeclaredConstraint = nullptr; 174 175 public: 176 TypeConstraint(NestedNameSpecifierLoc NNS, 177 DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, 178 ConceptDecl *NamedConcept, 179 const ASTTemplateArgumentListInfo *ArgsAsWritten, 180 Expr *ImmediatelyDeclaredConstraint) : 181 ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo, 182 FoundDecl, NamedConcept, ArgsAsWritten), 183 ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {} 184 185 /// \brief Get the immediately-declared constraint expression introduced by 186 /// this type-constraint, that is - the constraint expression that is added to 187 /// the associated constraints of the enclosing declaration in practice. 188 Expr *getImmediatelyDeclaredConstraint() const { 189 return ImmediatelyDeclaredConstraint; 190 } 191 192 void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const; 193 }; 194 195 } // clang 196 197 #endif // LLVM_CLANG_AST_ASTCONCEPT_H 198