Coverage Report

Created: 2020-11-24 06:42

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Sema/SemaConcept.h
Line
Count
Source (jump to first uncovered line)
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
71
      ConstraintExpr(ConstraintExpr) { };
36
37
  bool hasMatchingParameterMapping(ASTContext &C,
38
141
                                   const AtomicConstraint &Other) const {
39
141
    if (!ParameterMapping != !Other.ParameterMapping)
40
1
      return false;
41
140
    if (!ParameterMapping)
42
15
      return true;
43
125
    if (ParameterMapping->size() != Other.ParameterMapping->size())
44
2
      return false;
45
46
235
    
for (unsigned I = 0, S = ParameterMapping->size(); 123
I < S;
++I112
) {
47
130
      llvm::FoldingSetNodeID IDA, IDB;
48
130
      C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
49
130
          .Profile(IDA, C);
50
130
      C.getCanonicalTemplateArgument((*Other.ParameterMapping)[I].getArgument())
51
130
          .Profile(IDB, C);
52
130
      if (IDA != IDB)
53
18
        return false;
54
130
    }
55
105
    return true;
56
123
  }
57
58
200
  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
200
    if (ConstraintExpr != Other.ConstraintExpr)
72
98
      return false;
73
74
    // Check that the parameter lists are identical
75
102
    return hasMatchingParameterMapping(C, Other);
76
102
  }
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
71
  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
50
                std::move(LHS), std::move(RHS)}, Kind}} { };
99
100
137
  NormalizedConstraint(ASTContext &C, const NormalizedConstraint &Other) {
101
137
    if (Other.isAtomic()) {
102
122
      Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
103
15
    } else {
104
15
      Constraint = CompoundConstraint(
105
15
          new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
106
15
              NormalizedConstraint(C, Other.getLHS()),
107
15
              NormalizedConstraint(C, Other.getRHS())},
108
15
              Other.getCompoundKind());
109
15
    }
110
137
  }
111
  NormalizedConstraint(NormalizedConstraint &&Other):
112
711
      Constraint(Other.Constraint) {
113
711
    Other.Constraint = nullptr;
114
711
  }
115
  NormalizedConstraint &operator=(const NormalizedConstraint &Other) = delete;
116
0
  NormalizedConstraint &operator=(NormalizedConstraint &&Other) {
117
0
    if (&Other != this) {
118
0
      NormalizedConstraint Temp(std::move(Other));
119
0
      std::swap(Constraint, Temp.Constraint);
120
0
    }
121
0
    return *this;
122
0
  }
123
124
160
  CompoundConstraintKind getCompoundKind() const {
125
160
    assert(!isAtomic() && "getCompoundKind called on atomic constraint.");
126
160
    return Constraint.get<CompoundConstraint>().getInt();
127
160
  }
128
129
2.02k
  bool isAtomic() const { return Constraint.is<AtomicConstraint *>(); }
130
131
175
  NormalizedConstraint &getLHS() const {
132
175
    assert(!isAtomic() && "getLHS called on atomic constraint.");
133
175
    return Constraint.get<CompoundConstraint>().getPointer()->first;
134
175
  }
135
136
175
  NormalizedConstraint &getRHS() const {
137
175
    assert(!isAtomic() && "getRHS called on atomic constraint.");
138
175
    return Constraint.get<CompoundConstraint>().getPointer()->second;
139
175
  }
140
141
732
  AtomicConstraint *getAtomicConstraint() const {
142
732
    assert(isAtomic() &&
143
732
           "getAtomicConstraint called on non-atomic constraint.");
144
732
    return Constraint.get<AtomicConstraint *>();
145
732
  }
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