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> 23namespace clang { 24class ConceptDecl; 25class ConceptSpecializationExpr; 26 27/// The result of a constraint satisfaction check, containing the necessary 28/// information to diagnose an unsatisfied constraint. 29class 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 35public: 36 37 ConstraintSatisfaction() = default; 38 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 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. 68using 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. 77struct ASTConstraintSatisfaction final : 78 llvm::TrailingObjects<ASTConstraintSatisfaction, 79 UnsatisfiedConstraintRecord> { 80 std::size_t NumRecords; 81 bool IsSatisfied : 1; 82 83 const UnsatisfiedConstraintRecord *begin() const { 84 return getTrailingObjects<UnsatisfiedConstraintRecord>(); 85 } 86 87 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. 100class ConceptReference { 101protected: 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 125public: 126 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 135 ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(), 136 FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {} 137 138 const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { 139 return NestedNameSpec; 140 } 141 142 const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; } 143 144 SourceLocation getConceptNameLoc() const { 145 return getConceptNameInfo().getLoc(); 146 } 147 148 SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; } 149 150 NamedDecl *getFoundDecl() const { 151 return FoundDecl; 152 } 153 154 ConceptDecl *getNamedConcept() const { 155 return NamedConcept; 156 } 157 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) 164 bool hasExplicitTemplateArgs() const { 165 return ArgsAsWritten != nullptr; 166 } 167}; 168 169class TypeConstraint : public ConceptReference { 170 /// \brief The immediately-declared constraint expression introduced by this 171 /// type-constraint. 172 Expr *ImmediatelyDeclaredConstraint = nullptr; 173 174public: 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. 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