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