Skip to content

Commit 8d902f2

Browse files
authored
[clang] Force AttributedStmtClass to not be scope parents (#125370)
Example from the issue: ```c++ void Func(int x) { switch (x) { [[likely]] case 0: case 1: int i = 3; case 2: break; } } ``` Clang checks if ``case 2`` can be reachable by checking its scope. The variable declaration should create a scope containing ``case 2``, but due to the structure of the AST, ``case 2`` gets the scope of the ``likely`` statement, but not ``int i = 3;``. Therefore, I changed this code to force attribute statement not to be scope parents. Fixes #84072
1 parent 82bd148 commit 8d902f2

File tree

3 files changed

+21
-11
lines changed

3 files changed

+21
-11
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ Improvements to Clang's diagnostics
129129
which are supposed to only exist once per program, but may get duplicated when
130130
built into a shared library.
131131
- Fixed a bug where Clang's Analysis did not correctly model the destructor behavior of ``union`` members (#GH119415).
132+
- A statement attribute applied to a ``case`` label no longer suppresses
133+
'bypassing variable initialization' diagnostics (#84072).
132134

133135
Improvements to Clang's time-trace
134136
----------------------------------

clang/lib/Sema/JumpDiagnostics.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -597,15 +597,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
597597
LabelAndGotoScopes[S] = ParentScope;
598598
break;
599599

600-
case Stmt::AttributedStmtClass: {
601-
AttributedStmt *AS = cast<AttributedStmt>(S);
602-
if (GetMustTailAttr(AS)) {
603-
LabelAndGotoScopes[AS] = ParentScope;
604-
MustTailStmts.push_back(AS);
605-
}
606-
break;
607-
}
608-
609600
case Stmt::OpenACCComputeConstructClass: {
610601
unsigned NewParentScope = Scopes.size();
611602
OpenACCComputeConstruct *CC = cast<OpenACCComputeConstruct>(S);
@@ -649,7 +640,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
649640
continue;
650641
}
651642

652-
// Cases, labels, and defaults aren't "scope parents". It's also
643+
// Cases, labels, attributes, and defaults aren't "scope parents". It's also
653644
// important to handle these iteratively instead of recursively in
654645
// order to avoid blowing out the stack.
655646
while (true) {
@@ -658,7 +649,13 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
658649
Next = SC->getSubStmt();
659650
else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
660651
Next = LS->getSubStmt();
661-
else
652+
else if (AttributedStmt *AS = dyn_cast<AttributedStmt>(SubStmt)) {
653+
if (GetMustTailAttr(AS)) {
654+
LabelAndGotoScopes[AS] = ParentScope;
655+
MustTailStmts.push_back(AS);
656+
}
657+
Next = AS->getSubStmt();
658+
} else
662659
break;
663660

664661
LabelAndGotoScopes[SubStmt] = ParentScope;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang -fsyntax-only -std=c++20 -Xclang -verify %s
2+
3+
void Func(int x) {
4+
switch (x) {
5+
[[likely]] case 0:
6+
case 1:
7+
int i = 3; // expected-note {{jump bypasses variable initialization}}
8+
case 2: // expected-error {{cannot jump from switch statement to this case label}}
9+
break;
10+
}
11+
}

0 commit comments

Comments
 (0)