28
28
using namespace clang ;
29
29
using namespace sema ;
30
30
31
- bool
32
- Sema::CheckConstraintExpression (Expr *ConstraintExpression, Token NextToken,
33
- bool *PossibleNonPrimary,
34
- bool IsTrailingRequiresClause) {
31
+ namespace {
32
+ class LogicalBinOp {
33
+ OverloadedOperatorKind Op = OO_None;
34
+ const Expr *LHS = nullptr ;
35
+ const Expr *RHS = nullptr ;
36
+
37
+ public:
38
+ LogicalBinOp (const Expr *E) {
39
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
40
+ Op = BinaryOperator::getOverloadedOperator (BO->getOpcode ());
41
+ LHS = BO->getLHS ();
42
+ RHS = BO->getRHS ();
43
+ } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
44
+ Op = OO->getOperator ();
45
+ LHS = OO->getArg (0 );
46
+ RHS = OO->getArg (1 );
47
+ }
48
+ }
49
+
50
+ bool isAnd () const { return Op == OO_AmpAmp; }
51
+ bool isOr () const { return Op == OO_PipePipe; }
52
+ explicit operator bool () const { return isAnd () || isOr (); }
53
+
54
+ const Expr *getLHS () const { return LHS; }
55
+ const Expr *getRHS () const { return RHS; }
56
+ };
57
+ }
58
+
59
+ bool Sema::CheckConstraintExpression (const Expr *ConstraintExpression,
60
+ Token NextToken, bool *PossibleNonPrimary,
61
+ bool IsTrailingRequiresClause) {
35
62
// C++2a [temp.constr.atomic]p1
36
63
// ..E shall be a constant expression of type bool.
37
64
38
65
ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts ();
39
66
40
- if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {
41
- if (BinOp->getOpcode () == BO_LAnd || BinOp->getOpcode () == BO_LOr)
42
- return CheckConstraintExpression (BinOp->getLHS (), NextToken,
43
- PossibleNonPrimary) &&
44
- CheckConstraintExpression (BinOp->getRHS (), NextToken,
45
- PossibleNonPrimary);
67
+ if (LogicalBinOp BO = ConstraintExpression) {
68
+ return CheckConstraintExpression (BO.getLHS (), NextToken,
69
+ PossibleNonPrimary) &&
70
+ CheckConstraintExpression (BO.getRHS (), NextToken,
71
+ PossibleNonPrimary);
46
72
} else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
47
73
return CheckConstraintExpression (C->getSubExpr (), NextToken,
48
74
PossibleNonPrimary);
@@ -60,7 +86,7 @@ Sema::CheckConstraintExpression(Expr *ConstraintExpression, Token NextToken,
60
86
(NextToken.is (tok::l_paren) &&
61
87
(IsTrailingRequiresClause ||
62
88
(Type->isDependentType () &&
63
- IsDependentFunctionNameExpr (ConstraintExpression)) ||
89
+ isa<UnresolvedLookupExpr> (ConstraintExpression)) ||
64
90
Type->isFunctionType () ||
65
91
Type->isSpecificBuiltinType (BuiltinType::Overload))) ||
66
92
// We have the following case:
@@ -99,39 +125,37 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
99
125
AtomicEvaluator &&Evaluator) {
100
126
ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts ();
101
127
102
- if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
103
- if (BO->getOpcode () == BO_LAnd || BO->getOpcode () == BO_LOr) {
104
- if (calculateConstraintSatisfaction (S, BO->getLHS (), Satisfaction,
105
- Evaluator))
106
- return true ;
128
+ if (LogicalBinOp BO = ConstraintExpr) {
129
+ if (calculateConstraintSatisfaction (S, BO.getLHS (), Satisfaction,
130
+ Evaluator))
131
+ return true ;
107
132
108
- bool IsLHSSatisfied = Satisfaction.IsSatisfied ;
133
+ bool IsLHSSatisfied = Satisfaction.IsSatisfied ;
109
134
110
- if (BO-> getOpcode () == BO_LOr && IsLHSSatisfied)
111
- // [temp.constr.op] p3
112
- // A disjunction is a constraint taking two operands. To determine if
113
- // a disjunction is satisfied, the satisfaction of the first operand
114
- // is checked. If that is satisfied, the disjunction is satisfied.
115
- // Otherwise, the disjunction is satisfied if and only if the second
116
- // operand is satisfied.
117
- return false ;
135
+ if (BO. isOr () && IsLHSSatisfied)
136
+ // [temp.constr.op] p3
137
+ // A disjunction is a constraint taking two operands. To determine if
138
+ // a disjunction is satisfied, the satisfaction of the first operand
139
+ // is checked. If that is satisfied, the disjunction is satisfied.
140
+ // Otherwise, the disjunction is satisfied if and only if the second
141
+ // operand is satisfied.
142
+ return false ;
118
143
119
- if (BO-> getOpcode () == BO_LAnd && !IsLHSSatisfied)
120
- // [temp.constr.op] p2
121
- // A conjunction is a constraint taking two operands. To determine if
122
- // a conjunction is satisfied, the satisfaction of the first operand
123
- // is checked. If that is not satisfied, the conjunction is not
124
- // satisfied. Otherwise, the conjunction is satisfied if and only if
125
- // the second operand is satisfied.
126
- return false ;
144
+ if (BO. isAnd () && !IsLHSSatisfied)
145
+ // [temp.constr.op] p2
146
+ // A conjunction is a constraint taking two operands. To determine if
147
+ // a conjunction is satisfied, the satisfaction of the first operand
148
+ // is checked. If that is not satisfied, the conjunction is not
149
+ // satisfied. Otherwise, the conjunction is satisfied if and only if
150
+ // the second operand is satisfied.
151
+ return false ;
127
152
128
- return calculateConstraintSatisfaction (S, BO->getRHS (), Satisfaction,
129
- std::forward<AtomicEvaluator>(Evaluator));
130
- }
131
- }
132
- else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
153
+ return calculateConstraintSatisfaction (
154
+ S, BO.getRHS (), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
155
+ } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
133
156
return calculateConstraintSatisfaction (S, C->getSubExpr (), Satisfaction,
134
157
std::forward<AtomicEvaluator>(Evaluator));
158
+ }
135
159
136
160
// An atomic constraint expression
137
161
ExprResult SubstitutedAtomicExpr = Evaluator (ConstraintExpr);
@@ -725,19 +749,16 @@ NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
725
749
// - The normal form of an expression (E) is the normal form of E.
726
750
// [...]
727
751
E = E->IgnoreParenImpCasts ();
728
- if (auto *BO = dyn_cast<const BinaryOperator>(E)) {
729
- if (BO->getOpcode () == BO_LAnd || BO->getOpcode () == BO_LOr) {
730
- auto LHS = fromConstraintExpr (S, D, BO->getLHS ());
731
- if (!LHS)
732
- return None;
733
- auto RHS = fromConstraintExpr (S, D, BO->getRHS ());
734
- if (!RHS)
735
- return None;
752
+ if (LogicalBinOp BO = E) {
753
+ auto LHS = fromConstraintExpr (S, D, BO.getLHS ());
754
+ if (!LHS)
755
+ return None;
756
+ auto RHS = fromConstraintExpr (S, D, BO.getRHS ());
757
+ if (!RHS)
758
+ return None;
736
759
737
- return NormalizedConstraint (
738
- S.Context , std::move (*LHS), std::move (*RHS),
739
- BO->getOpcode () == BO_LAnd ? CCK_Conjunction : CCK_Disjunction);
740
- }
760
+ return NormalizedConstraint (S.Context , std::move (*LHS), std::move (*RHS),
761
+ BO.isAnd () ? CCK_Conjunction : CCK_Disjunction);
741
762
} else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
742
763
const NormalizedConstraint *SubNF;
743
764
{
0 commit comments