Coverage Report

Created: 2021-09-21 08:58

/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
// 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/Optional.h"
22
#include "llvm/ADT/SmallVector.h"
23
#include <string>
24
#include <utility>
25
26
namespace clang {
27
class Sema;
28
29
struct AtomicConstraint {
30
  const Expr *ConstraintExpr;
31
  Optional<MutableArrayRef<TemplateArgumentLoc>> ParameterMapping;
32
33
  AtomicConstraint(Sema &S, const Expr *ConstraintExpr) :
34
76
      ConstraintExpr(ConstraintExpr) { };
35
36
  bool hasMatchingParameterMapping(ASTContext &C,
37
152
                                   const AtomicConstraint &Other) const {
38
152
    if (!ParameterMapping != !Other.ParameterMapping)
39
1
      return false;
40
151
    if (!ParameterMapping)
41
15
      return true;
42
136
    if (ParameterMapping->size() != Other.ParameterMapping->size())
43
2
      return false;
44
45
248
    
for (unsigned I = 0, S = ParameterMapping->size(); 134
I < S;
++I114
) {
46
139
      llvm::FoldingSetNodeID IDA, IDB;
47
139
      C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
48
139
          .Profile(IDA, C);
49
139
      C.getCanonicalTemplateArgument((*Other.ParameterMapping)[I].getArgument())
50
139
          .Profile(IDB, C);
51
139
      if (IDA != IDB)
52
25
        return false;
53
139
    }
54
109
    return true;
55
134
  }
56
57
210
  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
210
    if (ConstraintExpr != Other.ConstraintExpr)
71
99
      return false;
72
73
    // Check that the parameter lists are identical
74
111
    return hasMatchingParameterMapping(C, Other);
75
210
  }
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
76
  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
56
                std::move(LHS), std::move(RHS)}, Kind}} { };
98
99
155
  NormalizedConstraint(ASTContext &C, const NormalizedConstraint &Other) {
100
155
    if (Other.isAtomic()) {
101
139
      Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
102
139
    } else {
103
16
      Constraint = CompoundConstraint(
104
16
          new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
105
16
              NormalizedConstraint(C, Other.getLHS()),
106
16
              NormalizedConstraint(C, Other.getRHS())},
107
16
              Other.getCompoundKind());
108
16
    }
109
155
  }
110
  NormalizedConstraint(NormalizedConstraint &&Other):
111
792
      Constraint(Other.Constraint) {
112
792
    Other.Constraint = nullptr;
113
792
  }
114
  NormalizedConstraint &operator=(const NormalizedConstraint &Other) = delete;
115
4
  NormalizedConstraint &operator=(NormalizedConstraint &&Other) {
116
4
    if (&Other != this) {
117
4
      NormalizedConstraint Temp(std::move(Other));
118
4
      std::swap(Constraint, Temp.Constraint);
119
4
    }
120
4
    return *this;
121
4
  }
122
123
177
  CompoundConstraintKind getCompoundKind() const {
124
177
    assert(!isAtomic() && "getCompoundKind called on atomic constraint.");
125
0
    return Constraint.get<CompoundConstraint>().getInt();
126
177
  }
127
128
2.26k
  bool isAtomic() const { return Constraint.is<AtomicConstraint *>(); }
129
130
193
  NormalizedConstraint &getLHS() const {
131
193
    assert(!isAtomic() && "getLHS called on atomic constraint.");
132
0
    return Constraint.get<CompoundConstraint>().getPointer()->first;
133
193
  }
134
135
193
  NormalizedConstraint &getRHS() const {
136
193
    assert(!isAtomic() && "getRHS called on atomic constraint.");
137
0
    return Constraint.get<CompoundConstraint>().getPointer()->second;
138
193
  }
139
140
821
  AtomicConstraint *getAtomicConstraint() const {
141
821
    assert(isAtomic() &&
142
821
           "getAtomicConstraint called on non-atomic constraint.");
143
0
    return Constraint.get<AtomicConstraint *>();
144
821
  }
145
146
private:
147
  static Optional<NormalizedConstraint>
148
  fromConstraintExprs(Sema &S, NamedDecl *D, ArrayRef<const Expr *> E);
149
  static Optional<NormalizedConstraint>
150
  fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E);
151
};
152
153
} // clang
154
155
#endif //LLVM_CLANG_SEMA_SEMACONCEPT_H