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> 23 namespace clang { 24 class ConceptDecl; 25 class ConceptSpecializationExpr; 26 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; 34 35 public: 36 37 ConstraintSatisfaction() = default; 38 ConstraintSatisfaction(const NamedDecl * ConstraintOwner,ArrayRef<TemplateArgument> TemplateArgs)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 Profile(llvm::FoldingSetNodeID & ID,const ASTContext & C)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. 68 using 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. 77 struct ASTConstraintSatisfaction final : 78 llvm::TrailingObjects<ASTConstraintSatisfaction, 79 UnsatisfiedConstraintRecord> { 80 std::size_t NumRecords; 81 bool IsSatisfied : 1; 82 beginfinal83 const UnsatisfiedConstraintRecord *begin() const { 84 return getTrailingObjects<UnsatisfiedConstraintRecord>(); 85 } 86 endfinal87 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. 100 class ConceptReference { 101 protected: 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 125 public: 126 ConceptReference(NestedNameSpecifierLoc NNS,SourceLocation TemplateKWLoc,DeclarationNameInfo ConceptNameInfo,NamedDecl * FoundDecl,ConceptDecl * NamedConcept,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) {} 134 ConceptReference()135 ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(), 136 FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {} 137 getNestedNameSpecifierLoc()138 const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { 139 return NestedNameSpec; 140 } 141 getConceptNameInfo()142 const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; } 143 getConceptNameLoc()144 SourceLocation getConceptNameLoc() const { 145 return getConceptNameInfo().getLoc(); 146 } 147 getTemplateKWLoc()148 SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; } 149 getFoundDecl()150 NamedDecl *getFoundDecl() const { 151 return FoundDecl; 152 } 153 getNamedConcept()154 ConceptDecl *getNamedConcept() const { 155 return NamedConcept; 156 } 157 getTemplateArgsAsWritten()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) hasExplicitTemplateArgs()164 bool hasExplicitTemplateArgs() const { 165 return ArgsAsWritten != nullptr; 166 } 167 }; 168 169 class TypeConstraint : public ConceptReference { 170 /// \brief The immediately-declared constraint expression introduced by this 171 /// type-constraint. 172 Expr *ImmediatelyDeclaredConstraint = nullptr; 173 174 public: TypeConstraint(NestedNameSpecifierLoc NNS,DeclarationNameInfo ConceptNameInfo,NamedDecl * FoundDecl,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,Expr * ImmediatelyDeclaredConstraint)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. getImmediatelyDeclaredConstraint()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