Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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