Skip to content

Commit 5ce0e96

Browse files
committed
[FOLD] correctly rebuild dependent binary operators
1 parent 365d975 commit 5ce0e96

File tree

3 files changed

+184
-18
lines changed

3 files changed

+184
-18
lines changed

clang/lib/Sema/SemaExpr.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15362,14 +15362,10 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
1536215362
}
1536315363

1536415364
if (getLangOpts().CPlusPlus) {
15365-
// If either expression is type-dependent, always build an
15366-
// overloaded op.
15367-
if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
15368-
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
15369-
15370-
// Otherwise, build an overloaded op if either expression has an
15371-
// overloadable type.
15372-
if (LHSExpr->getType()->isOverloadableType() ||
15365+
// Otherwise, build an overloaded op if either expression is type-dependent
15366+
// or has an overloadable type.
15367+
if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent() ||
15368+
LHSExpr->getType()->isOverloadableType() ||
1537315369
RHSExpr->getType()->isOverloadableType())
1537415370
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
1537515371
}

clang/lib/Sema/TreeTransform.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16236,10 +16236,11 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
1623616236
return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First);
1623716237
}
1623816238
} else {
16239-
if (!First->getType()->isOverloadableType() &&
16239+
if (!First->isTypeDependent() && !Second->isTypeDependent() &&
16240+
!First->getType()->isOverloadableType() &&
1624016241
!Second->getType()->isOverloadableType()) {
16241-
// Neither of the arguments is an overloadable type, so try to
16242-
// create a built-in binary operation.
16242+
// Neither of the arguments is type-dependent or has an overloadable
16243+
// type, so try to create a built-in binary operation.
1624316244
BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
1624416245
ExprResult Result
1624516246
= SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second);
@@ -16250,12 +16251,8 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
1625016251
}
1625116252
}
1625216253

16253-
// Add any functions found via argument-dependent lookup.
16254-
Expr *Args[2] = { First, Second };
16255-
unsigned NumArgs = 1 + (Second != nullptr);
16256-
1625716254
// Create the overloaded operator invocation for unary operators.
16258-
if (NumArgs == 1 || isPostIncDec) {
16255+
if (!Second || isPostIncDec) {
1625916256
UnaryOperatorKind Opc
1626016257
= UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
1626116258
return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First,
@@ -16264,8 +16261,8 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
1626416261

1626516262
// Create the overloaded operator invocation for binary operators.
1626616263
BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
16267-
ExprResult Result = SemaRef.CreateOverloadedBinOp(
16268-
OpLoc, Opc, Functions, Args[0], Args[1], RequiresADL);
16264+
ExprResult Result = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions,
16265+
First, Second, RequiresADL);
1626916266
if (Result.isInvalid())
1627016267
return ExprError();
1627116268

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// RUN: %clang_cc1 -std=c++20 -verify -Wno-unused %s
2+
3+
template<typename T, typename U>
4+
void operator->*(T, U);
5+
6+
template<typename T, typename U>
7+
void operator+(T, U);
8+
9+
template<typename T, typename U>
10+
void operator-(T, U);
11+
12+
template<typename T, typename U>
13+
void operator*(T, U);
14+
15+
template<typename T, typename U>
16+
void operator/(T, U);
17+
18+
template<typename T, typename U>
19+
void operator%(T, U);
20+
21+
template<typename T, typename U>
22+
void operator^(T, U);
23+
24+
template<typename T, typename U>
25+
void operator&(T, U);
26+
27+
template<typename T, typename U>
28+
void operator|(T, U);
29+
30+
template<typename T, typename U>
31+
void operator+=(T, U);
32+
33+
template<typename T, typename U>
34+
void operator-=(T, U);
35+
36+
template<typename T, typename U>
37+
void operator*=(T, U);
38+
39+
template<typename T, typename U>
40+
void operator/=(T, U);
41+
42+
template<typename T, typename U>
43+
void operator%=(T, U);
44+
45+
template<typename T, typename U>
46+
void operator^=(T, U);
47+
48+
template<typename T, typename U>
49+
void operator&=(T, U);
50+
51+
template<typename T, typename U>
52+
void operator|=(T, U);
53+
54+
template<typename T, typename U>
55+
void operator==(T, U);
56+
57+
template<typename T, typename U>
58+
void operator!=(T, U);
59+
60+
template<typename T, typename U>
61+
void operator<(T, U);
62+
63+
template<typename T, typename U>
64+
void operator>(T, U);
65+
66+
template<typename T, typename U>
67+
void operator<=(T, U);
68+
69+
template<typename T, typename U>
70+
void operator>=(T, U);
71+
72+
template<typename T, typename U>
73+
void operator<=>(T, U);
74+
75+
template<typename T, typename U>
76+
void operator&&(T, U);
77+
78+
template<typename T, typename U>
79+
void operator||(T, U);
80+
81+
template<typename T, typename U>
82+
void operator<<(T, U);
83+
84+
template<typename T, typename U>
85+
void operator>>(T, U);
86+
87+
template<typename T, typename U>
88+
void operator<<=(T, U);
89+
90+
template<typename T, typename U>
91+
void operator>>=(T, U);
92+
93+
template<typename T, typename U>
94+
void operator,(T, U);
95+
96+
template<typename T>
97+
void operator*(T);
98+
99+
template<typename T>
100+
void operator&(T);
101+
102+
template<typename T>
103+
void operator+(T);
104+
105+
template<typename T>
106+
void operator-(T);
107+
108+
template<typename T>
109+
void operator!(T);
110+
111+
template<typename T>
112+
void operator~(T);
113+
114+
template<typename T>
115+
void operator++(T);
116+
117+
template<typename T>
118+
void operator--(T);
119+
120+
template<typename T>
121+
void operator++(T, int);
122+
123+
template<typename T>
124+
void operator--(T, int);
125+
126+
template<typename T>
127+
void f(int *x) {
128+
[&](auto *y) {
129+
*y;
130+
&y;
131+
+y;
132+
-y; // expected-error {{invalid argument type 'auto *' to unary expression}}
133+
!y;
134+
~y; // expected-error {{invalid argument type 'auto *' to unary expression}}
135+
++y;
136+
--y;
137+
y++;
138+
y--;
139+
y->*x;
140+
y + x;
141+
y - x;
142+
y * x;
143+
y / x;
144+
y % x;
145+
y ^ x;
146+
y & x;
147+
y | x;
148+
y += x;
149+
y -= x;
150+
y *= x;
151+
y /= x;
152+
y %= x;
153+
y ^= x;
154+
y &= x;
155+
y |= x;
156+
y == x;
157+
y != x;
158+
y < x;
159+
y > x;
160+
y <= x;
161+
y >= x;
162+
y <=> x;
163+
y && x;
164+
y || x;
165+
y << x;
166+
y >> x;
167+
y <<= x;
168+
y >>= x;
169+
y, x;
170+
};
171+
}
172+
173+
template void f<int>(int*);

0 commit comments

Comments
 (0)