Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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