ASTConcept.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// \brief This file provides AST data structures related to concepts.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_AST_ASTCONCEPT_H
  19. #define LLVM_CLANG_AST_ASTCONCEPT_H
  20. #include "clang/AST/Expr.h"
  21. #include "clang/Basic/SourceLocation.h"
  22. #include "llvm/ADT/PointerUnion.h"
  23. #include "llvm/ADT/SmallVector.h"
  24. #include <utility>
  25. namespace clang {
  26. class ConceptDecl;
  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. public:
  35. ConstraintSatisfaction() = default;
  36. ConstraintSatisfaction(const NamedDecl *ConstraintOwner,
  37. ArrayRef<TemplateArgument> TemplateArgs) :
  38. ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(),
  39. TemplateArgs.end()) { }
  40. using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
  41. using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
  42. bool IsSatisfied = false;
  43. bool ContainsErrors = false;
  44. /// \brief Pairs of unsatisfied atomic constraint expressions along with the
  45. /// substituted constraint expr, if the template arguments could be
  46. /// substituted into them, or a diagnostic if substitution resulted in an
  47. /// invalid expression.
  48. llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details;
  49. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
  50. Profile(ID, C, ConstraintOwner, TemplateArgs);
  51. }
  52. static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
  53. const NamedDecl *ConstraintOwner,
  54. ArrayRef<TemplateArgument> TemplateArgs);
  55. bool HasSubstitutionFailure() {
  56. for (const auto &Detail : Details)
  57. if (Detail.second.dyn_cast<SubstitutionDiagnostic *>())
  58. return true;
  59. return false;
  60. }
  61. };
  62. /// Pairs of unsatisfied atomic constraint expressions along with the
  63. /// substituted constraint expr, if the template arguments could be
  64. /// substituted into them, or a diagnostic if substitution resulted in
  65. /// an invalid expression.
  66. using UnsatisfiedConstraintRecord =
  67. std::pair<const Expr *,
  68. llvm::PointerUnion<Expr *,
  69. std::pair<SourceLocation, StringRef> *>>;
  70. /// \brief The result of a constraint satisfaction check, containing the
  71. /// necessary information to diagnose an unsatisfied constraint.
  72. ///
  73. /// This is safe to store in an AST node, as opposed to ConstraintSatisfaction.
  74. struct ASTConstraintSatisfaction final :
  75. llvm::TrailingObjects<ASTConstraintSatisfaction,
  76. UnsatisfiedConstraintRecord> {
  77. std::size_t NumRecords;
  78. bool IsSatisfied : 1;
  79. bool ContainsErrors : 1;
  80. const UnsatisfiedConstraintRecord *begin() const {
  81. return getTrailingObjects<UnsatisfiedConstraintRecord>();
  82. }
  83. const UnsatisfiedConstraintRecord *end() const {
  84. return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords;
  85. }
  86. ASTConstraintSatisfaction(const ASTContext &C,
  87. const ConstraintSatisfaction &Satisfaction);
  88. ASTConstraintSatisfaction(const ASTContext &C,
  89. const ASTConstraintSatisfaction &Satisfaction);
  90. static ASTConstraintSatisfaction *
  91. Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
  92. static ASTConstraintSatisfaction *
  93. Rebuild(const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction);
  94. };
  95. /// \brief Common data class for constructs that reference concepts with
  96. /// template arguments.
  97. class ConceptReference {
  98. protected:
  99. // \brief The optional nested name specifier used when naming the concept.
  100. NestedNameSpecifierLoc NestedNameSpec;
  101. /// \brief The location of the template keyword, if specified when naming the
  102. /// concept.
  103. SourceLocation TemplateKWLoc;
  104. /// \brief The concept name used.
  105. DeclarationNameInfo ConceptName;
  106. /// \brief The declaration found by name lookup when the expression was
  107. /// created.
  108. /// Can differ from NamedConcept when, for example, the concept was found
  109. /// through a UsingShadowDecl.
  110. NamedDecl *FoundDecl;
  111. /// \brief The concept named.
  112. ConceptDecl *NamedConcept;
  113. /// \brief The template argument list source info used to specialize the
  114. /// concept.
  115. const ASTTemplateArgumentListInfo *ArgsAsWritten;
  116. public:
  117. ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
  118. DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
  119. ConceptDecl *NamedConcept,
  120. const ASTTemplateArgumentListInfo *ArgsAsWritten)
  121. : NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
  122. ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
  123. NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {}
  124. ConceptReference()
  125. : FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {}
  126. const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
  127. return NestedNameSpec;
  128. }
  129. const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; }
  130. SourceLocation getConceptNameLoc() const {
  131. return getConceptNameInfo().getLoc();
  132. }
  133. SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
  134. NamedDecl *getFoundDecl() const {
  135. return FoundDecl;
  136. }
  137. ConceptDecl *getNamedConcept() const {
  138. return NamedConcept;
  139. }
  140. const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
  141. return ArgsAsWritten;
  142. }
  143. /// \brief Whether or not template arguments were explicitly specified in the
  144. /// concept reference (they might not be in type constraints, for example)
  145. bool hasExplicitTemplateArgs() const {
  146. return ArgsAsWritten != nullptr;
  147. }
  148. };
  149. class TypeConstraint : public ConceptReference {
  150. /// \brief The immediately-declared constraint expression introduced by this
  151. /// type-constraint.
  152. Expr *ImmediatelyDeclaredConstraint = nullptr;
  153. public:
  154. TypeConstraint(NestedNameSpecifierLoc NNS,
  155. DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
  156. ConceptDecl *NamedConcept,
  157. const ASTTemplateArgumentListInfo *ArgsAsWritten,
  158. Expr *ImmediatelyDeclaredConstraint) :
  159. ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo,
  160. FoundDecl, NamedConcept, ArgsAsWritten),
  161. ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {}
  162. /// \brief Get the immediately-declared constraint expression introduced by
  163. /// this type-constraint, that is - the constraint expression that is added to
  164. /// the associated constraints of the enclosing declaration in practice.
  165. Expr *getImmediatelyDeclaredConstraint() const {
  166. return ImmediatelyDeclaredConstraint;
  167. }
  168. void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const;
  169. };
  170. } // clang
  171. #endif // LLVM_CLANG_AST_ASTCONCEPT_H
  172. #ifdef __GNUC__
  173. #pragma GCC diagnostic pop
  174. #endif