Skip to content

Commit 146866e

Browse files
committed
Revert "Reapply "[Clang][Sema] Earlier type checking for builtin unary operators (llvm#90500)" (llvm#92283)"
This reverts commit 1595988. rdar://131028403 Conflicts: clang/docs/ReleaseNotes.rst
1 parent 1fbdf73 commit 146866e

File tree

17 files changed

+263
-598
lines changed

17 files changed

+263
-598
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,6 @@ C++ Specific Potentially Breaking Changes
5656

5757
- Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906).
5858

59-
- Clang now performs semantic analysis for unary operators with dependent operands
60-
that are known to be of non-class non-enumeration type prior to instantiation.
61-
62-
This change uncovered a bug in libstdc++ 14.1.0 which may cause compile failures
63-
on systems using that version of libstdc++ and Clang 19, with an error that looks
64-
something like this:
65-
66-
.. code-block:: text
67-
68-
<source>:4:5: error: expression is not assignable
69-
4 | ++this;
70-
| ^ ~~~~
71-
72-
To fix this, update libstdc++ to version 14.1.1 or greater.
73-
7459
ABI Changes in This Version
7560
---------------------------
7661
- Fixed Microsoft name mangling of implicitly defined variables used for thread

clang/include/clang/AST/Type.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8079,10 +8079,7 @@ inline bool Type::isUndeducedType() const {
80798079
/// Determines whether this is a type for which one can define
80808080
/// an overloaded operator.
80818081
inline bool Type::isOverloadableType() const {
8082-
if (!CanonicalType->isDependentType())
8083-
return isRecordType() || isEnumeralType();
8084-
return !isArrayType() && !isFunctionType() && !isAnyPointerType() &&
8085-
!isMemberPointerType();
8082+
return isDependentType() || isRecordType() || isEnumeralType();
80868083
}
80878084

80888085
/// Determines whether this type is written as a typedef-name.

clang/lib/Sema/SemaExpr.cpp

Lines changed: 186 additions & 177 deletions
Large diffs are not rendered by default.

clang/lib/Sema/TreeTransform.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16313,11 +16313,10 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
1631316313
return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First);
1631416314
}
1631516315
} else {
16316-
if (!First->isTypeDependent() && !Second->isTypeDependent() &&
16317-
!First->getType()->isOverloadableType() &&
16316+
if (!First->getType()->isOverloadableType() &&
1631816317
!Second->getType()->isOverloadableType()) {
16319-
// Neither of the arguments is type-dependent or has an overloadable
16320-
// type, so try to create a built-in binary operation.
16318+
// Neither of the arguments is an overloadable type, so try to
16319+
// create a built-in binary operation.
1632116320
BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
1632216321
ExprResult Result
1632316322
= SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second);
@@ -16328,8 +16327,12 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
1632816327
}
1632916328
}
1633016329

16330+
// Add any functions found via argument-dependent lookup.
16331+
Expr *Args[2] = { First, Second };
16332+
unsigned NumArgs = 1 + (Second != nullptr);
16333+
1633116334
// Create the overloaded operator invocation for unary operators.
16332-
if (!Second || isPostIncDec) {
16335+
if (NumArgs == 1 || isPostIncDec) {
1633316336
UnaryOperatorKind Opc
1633416337
= UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
1633516338
return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First,
@@ -16338,8 +16341,8 @@ ExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(
1633816341

1633916342
// Create the overloaded operator invocation for binary operators.
1634016343
BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
16341-
ExprResult Result = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions,
16342-
First, Second, RequiresADL);
16344+
ExprResult Result = SemaRef.CreateOverloadedBinOp(
16345+
OpLoc, Opc, Functions, Args[0], Args[1], RequiresADL);
1634316346
if (Result.isInvalid())
1634416347
return ExprError();
1634516348

clang/test/AST/ast-dump-expr-json.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4261,9 +4261,9 @@ void TestNonADLCall3() {
42614261
// CHECK-NEXT: }
42624262
// CHECK-NEXT: },
42634263
// CHECK-NEXT: "type": {
4264-
// CHECK-NEXT: "qualType": "V"
4264+
// CHECK-NEXT: "qualType": "<dependent type>"
42654265
// CHECK-NEXT: },
4266-
// CHECK-NEXT: "valueCategory": "lvalue",
4266+
// CHECK-NEXT: "valueCategory": "prvalue",
42674267
// CHECK-NEXT: "isPostfix": false,
42684268
// CHECK-NEXT: "opcode": "*",
42694269
// CHECK-NEXT: "canOverflow": false,

clang/test/AST/ast-dump-expr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ void PrimaryExpressions(Ts... a) {
282282
// CHECK-NEXT: CompoundStmt
283283
// CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V'
284284
// CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:8> 'NULL TYPE'
285-
// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:8> 'V' lvalue prefix '*' cannot overflow
285+
// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:8> '<dependent type>' prefix '*' cannot overflow
286286
// CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' this
287287
}
288288
};

clang/test/AST/ast-dump-lambda.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ template <typename... Ts> void test(Ts... a) {
8181
// CHECK-NEXT: | | | `-CompoundStmt {{.*}} <col:15, col:16>
8282
// CHECK-NEXT: | | `-FieldDecl {{.*}} <col:8> col:8{{( imported)?}} implicit 'V'
8383
// CHECK-NEXT: | |-ParenListExpr {{.*}} <col:8> 'NULL TYPE'
84-
// CHECK-NEXT: | | `-UnaryOperator {{.*}} <col:8> 'V' lvalue prefix '*' cannot overflow
84+
// CHECK-NEXT: | | `-UnaryOperator {{.*}} <col:8> '<dependent type>' prefix '*' cannot overflow
8585
// CHECK-NEXT: | | `-CXXThisExpr {{.*}} <col:8> 'V *' this
8686
// CHECK-NEXT: | `-CompoundStmt {{.*}} <col:15, col:16>
8787
// CHECK-NEXT: |-DeclStmt {{.*}} <line:22:3, col:11>

clang/test/CXX/expr/expr.unary/expr.unary.general/p1.cpp

Lines changed: 0 additions & 65 deletions
This file was deleted.
Lines changed: 30 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,41 @@
1-
// RUN: %clang_cc1 -std=c++17 -Wno-unused -ast-dump %s -ast-dump-filter Test | FileCheck %s
1+
// RUN: %clang_cc1 -std=c++17 -ast-dump %s -ast-dump-filter Test | FileCheck %s
22

3-
namespace Test {
4-
template<typename T, typename U>
5-
void Unary(T t, T* pt, T U::* mpt, T(&ft)(), T(&at)[4]) {
6-
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '*' cannot overflow
7-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T'
8-
*t;
3+
struct A{};
94

10-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '+' cannot overflow
11-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T'
12-
+t;
5+
template <typename T, typename U>
6+
auto Test(T* pt, U* pu) {
7+
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '*'
8+
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
9+
(void)*pt;
1310

14-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '-' cannot overflow
15-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T'
16-
-t;
11+
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '++'
12+
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
13+
(void)(++pt);
1714

18-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '!' cannot overflow
19-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T'
20-
!t;
15+
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '+'
16+
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
17+
(void)(+pt);
2118

22-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '~' cannot overflow
23-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T'
24-
~t;
19+
// CHECK: BinaryOperator {{.*}} '<dependent type>' '+'
20+
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
21+
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
22+
(void)(pt + 3);
2523

26-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '&' cannot overflow
27-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T'
28-
&t;
24+
// CHECK: BinaryOperator {{.*}} '<dependent type>' '-'
25+
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
26+
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
27+
(void)(pt - pt);
2928

30-
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '++' cannot overflow
31-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T'
32-
++t;
29+
// CHECK: BinaryOperator {{.*}} '<dependent type>' '-'
30+
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
31+
// CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
32+
(void)(pt - pu);
3333

34-
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '--' cannot overflow
35-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T' lvalue ParmVar {{.*}} 't' 'T'
36-
--t;
34+
// CHECK: BinaryOperator {{.*}} '<dependent type>' '=='
35+
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
36+
// CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
37+
(void)(pt == pu);
3738

38-
// CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow
39-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
40-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
41-
*pt;
39+
}
4240

43-
// CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow
44-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
45-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
46-
+pt;
4741

48-
// CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow
49-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' <PointerToBoolean>
50-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <LValueToRValue>
51-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
52-
!pt;
53-
54-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '&' cannot overflow
55-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
56-
&pt;
57-
58-
// CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '++' cannot overflow
59-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
60-
++pt;
61-
62-
// CHECK: UnaryOperator {{.*}} 'T *' lvalue prefix '--' cannot overflow
63-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
64-
--pt;
65-
66-
// CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow
67-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' <MemberPointerToBoolean>
68-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T U::*' <LValueToRValue>
69-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*'
70-
!mpt;
71-
72-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '&' cannot overflow
73-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T U::*' lvalue ParmVar {{.*}} 'mpt' 'T U::*'
74-
&mpt;
75-
76-
// CHECK: UnaryOperator {{.*}} 'T ()' lvalue prefix '*' cannot overflow
77-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' <FunctionToPointerDecay>
78-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()'
79-
*ft;
80-
81-
// CHECK: UnaryOperator {{.*}} 'T (*)()' prefix '+' cannot overflow
82-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' <FunctionToPointerDecay>
83-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()'
84-
+ft;
85-
86-
// CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow
87-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' <PointerToBoolean>
88-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T (*)()' <FunctionToPointerDecay>
89-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()'
90-
!ft;
91-
92-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '&' cannot overflow
93-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T ()' lvalue ParmVar {{.*}} 'ft' 'T (&)()'
94-
&ft;
95-
96-
// CHECK: UnaryOperator {{.*}} 'T' lvalue prefix '*' cannot overflow
97-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <ArrayToPointerDecay>
98-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]'
99-
*at;
100-
101-
// CHECK: UnaryOperator {{.*}} 'T *' prefix '+' cannot overflow
102-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <ArrayToPointerDecay>
103-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]'
104-
+at;
105-
106-
// CHECK: UnaryOperator {{.*}} 'bool' prefix '!' cannot overflow
107-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'bool' <PointerToBoolean>
108-
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'T *' <ArrayToPointerDecay>
109-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]'
110-
!at;
111-
112-
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '&' cannot overflow
113-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T[4]' lvalue ParmVar {{.*}} 'at' 'T (&)[4]'
114-
&at;
115-
}
116-
117-
template<typename T, typename U>
118-
void Binary(T* pt, U* pu) {
119-
// CHECK: BinaryOperator {{.*}} '<dependent type>' '+'
120-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
121-
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
122-
pt + 3;
123-
124-
// CHECK: BinaryOperator {{.*}} '<dependent type>' '-'
125-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
126-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
127-
pt - pt;
128-
129-
// CHECK: BinaryOperator {{.*}} '<dependent type>' '-'
130-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
131-
// CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
132-
pt - pu;
133-
134-
// CHECK: BinaryOperator {{.*}} '<dependent type>' '=='
135-
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
136-
// CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
137-
pt == pu;
138-
}
139-
} // namespace Test

clang/test/CXX/over/over.built/p10.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ void f(int i, float f, bool b, char c, int* pi, A* pa, T* pt) {
1515

1616
(void)-pi; // expected-error {{invalid argument type}}
1717
(void)-pa; // expected-error {{invalid argument type}}
18-
(void)-pt; // expected-error {{invalid argument type}}
18+
(void)-pt; // FIXME: we should be able to give an error here.
1919
}
2020

clang/test/CXX/over/over.built/p11.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ void f(int i, float f, bool b, char c, int* pi, T* pt) {
77
(void)~b;
88
(void)~c;
99
(void)~pi; // expected-error {{invalid argument type}}
10-
(void)~pt; // expected-error {{invalid argument type}}
10+
(void)~pt; // FIXME: we should be able to give an error here.
1111
}
1212

0 commit comments

Comments
 (0)