SemaConcept.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- SemaConcept.h - Semantic Analysis for Constraints and Concepts ----===//
  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. // This file provides semantic analysis for C++ constraints and concepts.
  15. ///
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_CLANG_SEMA_SEMACONCEPT_H
  18. #define LLVM_CLANG_SEMA_SEMACONCEPT_H
  19. #include "clang/AST/ASTConcept.h"
  20. #include "clang/AST/ASTContext.h"
  21. #include "clang/AST/Expr.h"
  22. #include "clang/AST/DeclTemplate.h"
  23. #include "clang/Basic/SourceLocation.h"
  24. #include "llvm/ADT/PointerUnion.h"
  25. #include "llvm/ADT/Optional.h"
  26. #include "llvm/ADT/SmallVector.h"
  27. #include <string>
  28. #include <utility>
  29. namespace clang {
  30. class Sema;
  31. struct AtomicConstraint {
  32. const Expr *ConstraintExpr;
  33. Optional<MutableArrayRef<TemplateArgumentLoc>> ParameterMapping;
  34. AtomicConstraint(Sema &S, const Expr *ConstraintExpr) :
  35. ConstraintExpr(ConstraintExpr) { };
  36. bool hasMatchingParameterMapping(ASTContext &C,
  37. const AtomicConstraint &Other) const {
  38. if (!ParameterMapping != !Other.ParameterMapping)
  39. return false;
  40. if (!ParameterMapping)
  41. return true;
  42. if (ParameterMapping->size() != Other.ParameterMapping->size())
  43. return false;
  44. for (unsigned I = 0, S = ParameterMapping->size(); I < S; ++I) {
  45. llvm::FoldingSetNodeID IDA, IDB;
  46. C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
  47. .Profile(IDA, C);
  48. C.getCanonicalTemplateArgument((*Other.ParameterMapping)[I].getArgument())
  49. .Profile(IDB, C);
  50. if (IDA != IDB)
  51. return false;
  52. }
  53. return true;
  54. }
  55. bool subsumes(ASTContext &C, const AtomicConstraint &Other) const {
  56. // C++ [temp.constr.order] p2
  57. // - an atomic constraint A subsumes another atomic constraint B
  58. // if and only if the A and B are identical [...]
  59. //
  60. // C++ [temp.constr.atomic] p2
  61. // Two atomic constraints are identical if they are formed from the
  62. // same expression and the targets of the parameter mappings are
  63. // equivalent according to the rules for expressions [...]
  64. // We do not actually substitute the parameter mappings into the
  65. // constraint expressions, therefore the constraint expressions are
  66. // the originals, and comparing them will suffice.
  67. if (ConstraintExpr != Other.ConstraintExpr)
  68. return false;
  69. // Check that the parameter lists are identical
  70. return hasMatchingParameterMapping(C, Other);
  71. }
  72. };
  73. /// \brief A normalized constraint, as defined in C++ [temp.constr.normal], is
  74. /// either an atomic constraint, a conjunction of normalized constraints or a
  75. /// disjunction of normalized constraints.
  76. struct NormalizedConstraint {
  77. friend class Sema;
  78. enum CompoundConstraintKind { CCK_Conjunction, CCK_Disjunction };
  79. using CompoundConstraint = llvm::PointerIntPair<
  80. std::pair<NormalizedConstraint, NormalizedConstraint> *, 1,
  81. CompoundConstraintKind>;
  82. llvm::PointerUnion<AtomicConstraint *, CompoundConstraint> Constraint;
  83. NormalizedConstraint(AtomicConstraint *C): Constraint{C} { };
  84. NormalizedConstraint(ASTContext &C, NormalizedConstraint LHS,
  85. NormalizedConstraint RHS, CompoundConstraintKind Kind)
  86. : Constraint{CompoundConstraint{
  87. new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
  88. std::move(LHS), std::move(RHS)}, Kind}} { };
  89. NormalizedConstraint(ASTContext &C, const NormalizedConstraint &Other) {
  90. if (Other.isAtomic()) {
  91. Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
  92. } else {
  93. Constraint = CompoundConstraint(
  94. new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
  95. NormalizedConstraint(C, Other.getLHS()),
  96. NormalizedConstraint(C, Other.getRHS())},
  97. Other.getCompoundKind());
  98. }
  99. }
  100. NormalizedConstraint(NormalizedConstraint &&Other):
  101. Constraint(Other.Constraint) {
  102. Other.Constraint = nullptr;
  103. }
  104. NormalizedConstraint &operator=(const NormalizedConstraint &Other) = delete;
  105. NormalizedConstraint &operator=(NormalizedConstraint &&Other) {
  106. if (&Other != this) {
  107. NormalizedConstraint Temp(std::move(Other));
  108. std::swap(Constraint, Temp.Constraint);
  109. }
  110. return *this;
  111. }
  112. CompoundConstraintKind getCompoundKind() const {
  113. assert(!isAtomic() && "getCompoundKind called on atomic constraint.");
  114. return Constraint.get<CompoundConstraint>().getInt();
  115. }
  116. bool isAtomic() const { return Constraint.is<AtomicConstraint *>(); }
  117. NormalizedConstraint &getLHS() const {
  118. assert(!isAtomic() && "getLHS called on atomic constraint.");
  119. return Constraint.get<CompoundConstraint>().getPointer()->first;
  120. }
  121. NormalizedConstraint &getRHS() const {
  122. assert(!isAtomic() && "getRHS called on atomic constraint.");
  123. return Constraint.get<CompoundConstraint>().getPointer()->second;
  124. }
  125. AtomicConstraint *getAtomicConstraint() const {
  126. assert(isAtomic() &&
  127. "getAtomicConstraint called on non-atomic constraint.");
  128. return Constraint.get<AtomicConstraint *>();
  129. }
  130. private:
  131. static Optional<NormalizedConstraint>
  132. fromConstraintExprs(Sema &S, NamedDecl *D, ArrayRef<const Expr *> E);
  133. static Optional<NormalizedConstraint>
  134. fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E);
  135. };
  136. } // clang
  137. #endif // LLVM_CLANG_SEMA_SEMACONCEPT_H
  138. #ifdef __GNUC__
  139. #pragma GCC diagnostic pop
  140. #endif