cor3ntin updated this revision to Diff 542813.
cor3ntin added a comment.
Rebase + add test
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D154696/new/
https://reviews.llvm.org/D154696
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/JumpDiagnostics.cpp
clang/lib/Sema/SemaExpr.cpp
clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
clang/test/Sema/asm-goto.cpp
clang/test/Sema/scope-check.c
clang/test/SemaCXX/constant-expression-cxx14.cpp
clang/test/SemaObjC/scope-check.m
Index: clang/test/SemaObjC/scope-check.m
===================================================================
--- clang/test/SemaObjC/scope-check.m
+++ clang/test/SemaObjC/scope-check.m
@@ -15,7 +15,7 @@
} @finally {// expected-note {{jump bypasses initialization of @finally block}}
L3: ;
}
-
+
@try {
goto L4; // expected-error{{cannot jump}}
goto L5; // expected-error{{cannot jump}}
@@ -27,8 +27,8 @@
} @finally { // expected-note {{jump bypasses initialization of @finally block}}
L4: ;
}
-
-
+
+
@try { // expected-note 2 {{jump bypasses initialization of @try block}}
L7: ;
} @catch (C *c) {
@@ -36,21 +36,18 @@
} @finally {
goto L7; // expected-error{{cannot jump}}
}
-
+
goto L8; // expected-error{{cannot jump}}
- @try {
+ @try {
} @catch (A *c) {
} @catch (B *c) {
} @catch (C *c) { // expected-note {{jump bypasses initialization of @catch block}}
L8: ;
}
-
- // rdar://6810106
id X;
goto L9; // expected-error{{cannot jump}}
- goto L10; // ok
- @synchronized // expected-note {{jump bypasses initialization of @synchronized block}}
- ( ({ L10: ; X; })) {
+ @synchronized (X) // expected-note {{jump bypasses initialization of @synchronized block}}
+ {
L9:
;
}
@@ -90,7 +87,7 @@
goto L0; // expected-error {{cannot jump}}
typedef int A[n]; // expected-note {{jump bypasses initialization of VLA typedef}}
L0:
-
+
goto L1; // expected-error {{cannot jump}}
A b, c[10]; // expected-note 2 {{jump bypasses initialization of variable length array}}
L1:
Index: clang/test/SemaCXX/constant-expression-cxx14.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -831,8 +831,9 @@
case 0:
return 0;
- ({
- case 1: // expected-note {{not supported}}
+ ({ // expected-note {{jump enters a statement expression}}
+ case 1:// expected-error {{cannot jump from switch statement to this case label}} \
+ // expected-note {{not supported}}
return 1;
});
}
Index: clang/test/Sema/scope-check.c
===================================================================
--- clang/test/Sema/scope-check.c
+++ clang/test/Sema/scope-check.c
@@ -65,7 +65,8 @@
// Statement expressions.
goto L3; // expected-error {{cannot jump from this goto statement to its label}}
- int Y = ({ int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
+ int Y = ({ int a[x]; // expected-note {{jump bypasses initialization of variable length array}} \
+ // expected-note {{jump enters a statement expression}}
L3: 4; });
goto L4; // expected-error {{cannot jump from this goto statement to its label}}
@@ -107,25 +108,25 @@
4; })];
L10:; // bad
}
-
+
{
// FIXME: Crashes goto checker.
//goto L11;// ok
//int A[({ L11: 4; })];
}
-
+
{
goto L12;
-
+
int y = 4; // fixme-warn: skips initializer.
L12:
;
}
-
+
// Statement expressions 2.
goto L1; // expected-error {{cannot jump from this goto statement to its label}}
- return x == ({
- int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
+ return x == ({ // expected-note {{jump enters a statement expression}}
+ int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
L1:
42; });
}
@@ -232,3 +233,27 @@
// rdar://9024687
int test16(int [sizeof &&z]); // expected-error {{use of address-of-label extension outside of a function body}}
+
+void GH63682() {
+ {
+ goto L; // expected-error {{cannot jump from this goto statement to its label}}
+ (void)sizeof (int){({ L:; 1; })}; // expected-note {{jump enters a statement expression}}
+ }
+ {
+ goto M; // expected-error {{cannot jump from this goto statement to its label}}
+ (void)({ M:; 1; }); // expected-note {{jump enters a statement expression}}
+ }
+ {
+ (void)({ goto N; 1; }); // ok
+ N: ;
+ }
+ {
+ (void)sizeof (int){({ goto O; 1; })}; // ok (not evaluated)
+ O: ;
+ }
+ {
+ (void)sizeof(({goto P;}), 0); // expected-error {{cannot jump from this goto statement to its label}}
+ return;
+ (void)({P:1;}); // expected-note {{jump enters a statement expression}}
+ }
+}
Index: clang/test/Sema/asm-goto.cpp
===================================================================
--- clang/test/Sema/asm-goto.cpp
+++ clang/test/Sema/asm-goto.cpp
@@ -50,8 +50,9 @@
// expected-error@+2 {{cannot jump from this asm goto statement to one of its possible targets}}
// expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}}
asm volatile goto("testl %0, %0; jne %l1;" :: "r"(n)::label_true, loop);
- // expected-note@+2 {{jump bypasses initialization of variable length array}}
- // expected-note@+1 {{possible target of asm goto statement}}
+ // expected-note@+3 {{jump bypasses initialization of variable length array}}
+ // expected-note@+2 {{possible target of asm goto statement}}
+ // expected-note@+1 {{jump enters a statement expression}}
return ({int a[n];label_true: 2;});
// expected-note@+1 {{jump bypasses initialization of variable length array}}
int b[n];
@@ -69,3 +70,17 @@
asm goto(""::::l1);
l1:;
}
+
+void statement_expressions() {
+ ({
+ __label__ label;
+ asm goto("" : : : : label);
+ label:;
+ });
+
+ ({
+ __label__ label;
+ asm goto("" : : : : label);
+ label:;
+ });
+}
Index: clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
===================================================================
--- clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
+++ clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
@@ -153,7 +153,8 @@
void evil_things() {
goto evil_label; // expected-error {{cannot jump}}
- if constexpr (true || ({evil_label: false;})) {} // expected-note {{constexpr if}}
+ if constexpr (true || ({evil_label: false;})) {} // expected-note {{constexpr if}} \
+ // expected-note {{jump enters a statement expression}}
if constexpr (true) // expected-note {{constexpr if}}
goto surprise; // expected-error {{cannot jump}}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -16509,6 +16509,8 @@
void Sema::ActOnStartStmtExpr() {
PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
+ // Make sure we diagnose jumping into a statement expression.
+ setFunctionHasBranchProtectedScope();
}
void Sema::ActOnStmtExprError() {
Index: clang/lib/Sema/JumpDiagnostics.cpp
===================================================================
--- clang/lib/Sema/JumpDiagnostics.cpp
+++ clang/lib/Sema/JumpDiagnostics.cpp
@@ -466,6 +466,21 @@
return;
}
+ case Stmt::StmtExprClass: {
+ // [GNU]
+ // Jumping into a statement expression with goto or using
+ // a switch statement outside the statement expression with
+ // a case or default label inside the statement expression is not permitted.
+ // Jumping out of a statement expression is permitted.
+ StmtExpr *SE = cast<StmtExpr>(S);
+ unsigned NewParentScope = Scopes.size();
+ Scopes.push_back(GotoScope(ParentScope,
+ diag::note_enters_statement_expression,
+ /*OutDiag=*/0, SE->getBeginLoc()));
+ BuildScopeInformation(SE->getSubStmt(), NewParentScope);
+ return;
+ }
+
case Stmt::ObjCAtTryStmtClass: {
// Disallow jumps into any part of an @try statement by pushing a scope and
// walking all sub-stmts in that scope.
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6219,6 +6219,8 @@
"to destroy">;
def note_enters_compound_literal_scope : Note<
"jump enters lifetime of a compound literal that is non-trivial to destruct">;
+def note_enters_statement_expression : Note<
+ "jump enters a statement expression">;
def note_exits_cleanup : Note<
"jump exits scope of variable with __attribute__((cleanup))">;
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -660,6 +660,9 @@
- Fixed false positive error diagnostic observed from mixing ``asm goto`` with
``__attribute__((cleanup()))`` variables falsely warning that jumps to
non-targets would skip cleanup.
+- Correcly diagnose jumps into statement expressions.
+ This ensures the behavior of Clang is consistent with GCC.
+ (`#63682 <https://github.com/llvm/llvm-project/issues/63682>`_)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -949,7 +952,7 @@
- The ``hasBody`` matcher now matches coroutine body nodes in
``CoroutineBodyStmts``.
-
+
- Add ``arrayInitIndexExpr`` and ``arrayInitLoopExpr`` matchers.
clang-format
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits