Coverage Report

Created: 2020-02-25 14:32

/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
63
      ConstraintExpr(ConstraintExpr) { };
36
37
  bool hasMatchingParameterMapping(ASTContext &C,
38
126
                                   const AtomicConstraint &Other) const {
39
126
    if (!ParameterMapping != !Other.ParameterMapping)
40
1
      return false;
41
125
    if (!ParameterMapping)
42
15
      return true;
43
110
    if (ParameterMapping->size() != Other.ParameterMapping->size())
44
0
      return false;
45
110
46
217
    
for (unsigned I = 0, S = ParameterMapping->size(); 110
I < S;
++I107
) {
47
125
      llvm::FoldingSetNodeID IDA, IDB;
48
125
      C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
49
125
          .Profile(IDA, C);
50
125
      C.getCanonicalTemplateArgument((*Other.ParameterMapping)[I].getArgument())
51
125
          .Profile(IDB, C);
52
125
      if (IDA != IDB)
53
18
        return false;
54
125
    }
55
110
    
return true92
;
56
110
  }
57
58
166
  bool subsumes(ASTContext &C, const AtomicConstraint &Other) const {
59
166
    // C++ [temp.constr.order] p2
60
166
    //   - an atomic constraint A subsumes another atomic constraint B
61
166
    //     if and only if the A and B are identical [...]
62
166
    //
63
166
    // C++ [temp.constr.atomic] p2
64
166
    //   Two atomic constraints are identical if they are formed from the
65
166
    //   same expression and the targets of the parameter mappings are
66
166
    //   equivalent according to the rules for expressions [...]
67
166
68
166
    // We do not actually substitute the parameter mappings into the
69
166
    // constraint expressions, therefore the constraint expressions are
70
166
    // the originals, and comparing them will suffice.
71
166
    if (ConstraintExpr != Other.ConstraintExpr)
72
77
      return false;
73
89
74
89
    // Check that the parameter lists are identical
75
89
    return hasMatchingParameterMapping(C, Other);
76
89
  }
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
63
  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
42
                std::move(LHS), std::move(RHS)}, Kind}} { };
99
100
112
  NormalizedConstraint(ASTContext &C, const NormalizedConstraint &Other) {
101
112
    if (Other.isAtomic()) {
102
100
      Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
103
100
    } else {
104
12
      Constraint = CompoundConstraint(
105
12
          new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
106
12
              NormalizedConstraint(C, Other.getLHS()),
107
12
              NormalizedConstraint(C, Other.getRHS())},
108
12
              Other.getCompoundKind());
109
12
    }
110
112
  }
111
  NormalizedConstraint(NormalizedConstraint &&Other):
112
600
      Constraint(Other.Constraint) {
113
600
    Other.Constraint = nullptr;
114
600
  }
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
133
  CompoundConstraintKind getCompoundKind() const {
125
133
    assert(!isAtomic() && "getCompoundKind called on atomic constraint.");
126
133
    return Constraint.get<CompoundConstraint>().getInt();
127
133
  }
128
129
1.68k
  bool isAtomic() const { return Constraint.is<AtomicConstraint *>(); }
130
131
145
  NormalizedConstraint &getLHS() const {
132
145
    assert(!isAtomic() && "getLHS called on atomic constraint.");
133
145
    return Constraint.get<CompoundConstraint>().getPointer()->first;
134
145
  }
135
136
145
  NormalizedConstraint &getRHS() const {
137
145
    assert(!isAtomic() && "getRHS called on atomic constraint.");
138
145
    return Constraint.get<CompoundConstraint>().getPointer()->second;
139
145
  }
140
141
606
  AtomicConstraint *getAtomicConstraint() const {
142
606
    assert(isAtomic() &&
143
606
           "getAtomicConstraint called on non-atomic constraint.");
144
606
    return Constraint.get<AtomicConstraint *>();
145
606
  }
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