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