From 97ba481f3f45e5b63b4a354bfb471ce146b7de57 Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 2 Aug 2010 23:33:14 +0000 Subject: [PATCH] Labels (and case statement) don't create independent scope parents for the purposes of the jump checker. Also extend Ted's iteration fix to labels. Fixes PR7789. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110082 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 +-- lib/Sema/JumpDiagnostics.cpp | 34 ++++++++++++---------- test/Sema/scope-check.c | 32 ++++++++++---------- test/SemaCXX/scope-check.cpp | 18 ++++++++++++ 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 283dab70dc..ef59f985db 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1855,9 +1855,9 @@ def warn_missing_braces : Warning< def err_redefinition_of_label : Error<"redefinition of label '%0'">; def err_undeclared_label_use : Error<"use of undeclared label '%0'">; -def err_goto_into_protected_scope : Error<"illegal goto into protected scope">; +def err_goto_into_protected_scope : Error<"goto into protected scope">; def err_switch_into_protected_scope : Error< - "illegal switch case into protected scope">; + "switch case is in protected scope">; def err_indirect_goto_without_addrlabel : Error< "indirect goto in function with no address-of-label expressions">; def warn_indirect_goto_in_protected_scope : Warning< diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index f696d6acbf..866a358e13 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -180,22 +180,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { // If we found a label, remember that it is in ParentScope scope. switch (S->getStmtClass()) { - case Stmt::LabelStmtClass: - case Stmt::DefaultStmtClass: - LabelAndGotoScopes[S] = ParentScope; - break; - case Stmt::CaseStmtClass: { - // Specially handle CaseStmts since they can nest each other in the - // AST and blow out the stack when we walk them. - CaseStmt *CS = cast(S); - do { - LabelAndGotoScopes[CS] = ParentScope; - S = CS; // 'CS' is the new current statement (if it isn't already). - CS = dyn_cast(CS->getSubStmt()); - } while (CS); - break; - } - case Stmt::AddrLabelExprClass: IndirectJumpTargets.push_back(cast(S)->getLabel()); break; @@ -235,6 +219,24 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { Stmt *SubStmt = *CI; if (SubStmt == 0) continue; + // Cases, labels, and defaults aren't "scope parents". It's also + // important to handle these iteratively instead of recursively in + // order to avoid blowing out the stack. + while (true) { + Stmt *Next; + if (isa(SubStmt)) + Next = cast(SubStmt)->getSubStmt(); + else if (isa(SubStmt)) + Next = cast(SubStmt)->getSubStmt(); + else if (isa(SubStmt)) + Next = cast(SubStmt)->getSubStmt(); + else + break; + + LabelAndGotoScopes[SubStmt] = ParentScope; + SubStmt = Next; + } + // If this is a declstmt with a VLA definition, it defines a scope from here // to the end of the containing context. if (DeclStmt *DS = dyn_cast(SubStmt)) { diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c index f3881ed086..4ccb64c9aa 100644 --- a/test/Sema/scope-check.c +++ b/test/Sema/scope-check.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu99 %s -Wno-unreachable-code int test1(int x) { - goto L; // expected-error{{illegal goto into protected scope}} + goto L; // expected-error{{goto into protected scope}} int a[x]; // expected-note {{jump bypasses initialization of variable length array}} int b[x]; // expected-note {{jump bypasses initialization of variable length array}} L: @@ -9,7 +9,7 @@ int test1(int x) { } int test2(int x) { - goto L; // expected-error{{illegal goto into protected scope}} + goto L; // expected-error{{goto into protected scope}} typedef int a[x]; // expected-note {{jump bypasses initialization of VLA typedef}} L: return sizeof(a); @@ -18,14 +18,14 @@ int test2(int x) { void test3clean(int*); int test3() { - goto L; // expected-error{{illegal goto into protected scope}} + goto L; // expected-error{{goto into protected scope}} int a __attribute((cleanup(test3clean))); // expected-note {{jump bypasses initialization of variable with __attribute__((cleanup))}} L: return a; } int test4(int x) { - goto L; // expected-error{{illegal goto into protected scope}} + goto L; // expected-error{{goto into protected scope}} int a[x]; // expected-note {{jump bypasses initialization of variable length array}} test4(x); L: @@ -50,7 +50,7 @@ void test7(int x) { switch (x) { case 1: ; int a[x]; // expected-note {{jump bypasses initialization of variable length array}} - case 2: // expected-error {{illegal switch case into protected scope}} + case 2: // expected-error {{switch case is in protected scope}} a[1] = 2; break; } @@ -58,17 +58,17 @@ void test7(int x) { int test8(int x) { // For statement. - goto L2; // expected-error {{illegal goto into protected scope}} + goto L2; // expected-error {{goto into protected scope}} for (int arr[x]; // expected-note {{jump bypasses initialization of variable length array}} ; ++x) L2:; // Statement expressions. - goto L3; // expected-error {{illegal goto into protected scope}} + goto L3; // expected-error {{goto into protected scope}} int Y = ({ int a[x]; // expected-note {{jump bypasses initialization of variable length array}} L3: 4; }); - goto L4; // expected-error {{illegal goto into protected scope}} + goto L4; // expected-error {{goto into protected scope}} { int A[x], // expected-note {{jump bypasses initialization of variable length array}} B[x]; // expected-note {{jump bypasses initialization of variable length array}} @@ -91,7 +91,7 @@ int test8(int x) { int A[x], B = ({ if (x) goto L7; else - goto L8; // expected-error {{illegal goto into protected scope}} + goto L8; // expected-error {{goto into protected scope}} 4; }), C[x]; // expected-note {{jump bypasses initialization of variable length array}} L8:; // bad @@ -103,7 +103,7 @@ int test8(int x) { goto L9; else // FIXME: - goto L10; // fixme-error {{illegal goto into protected scope}} + goto L10; // fixme-error {{goto into protected scope}} 4; })]; L10:; // bad } @@ -123,7 +123,7 @@ int test8(int x) { } // Statement expressions 2. - goto L1; // expected-error {{illegal goto into protected scope}} + goto L1; // expected-error {{goto into protected scope}} return x == ({ int a[x]; // expected-note {{jump bypasses initialization of variable length array}} L1: @@ -151,14 +151,14 @@ L4: } void test10(int n, void *P) { - goto L0; // expected-error {{illegal goto into protected scope}} + goto L0; // expected-error {{goto into protected scope}} typedef int A[n]; // expected-note {{jump bypasses initialization of VLA typedef}} L0: - goto L1; // expected-error {{illegal goto into protected scope}} + goto L1; // expected-error {{goto into protected scope}} A b, c[10]; // expected-note 2 {{jump bypasses initialization of variable length array}} L1: - goto L2; // expected-error {{illegal goto into protected scope}} + goto L2; // expected-error {{goto into protected scope}} A d[n]; // expected-note {{jump bypasses initialization of variable length array}} L2: return; @@ -171,7 +171,7 @@ void test11(int n) { case 2: case 3:; int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}} - case 4: // expected-error {{illegal switch case into protected scope}} + case 4: // expected-error {{switch case is in protected scope}} return; } }; @@ -185,7 +185,7 @@ void test12(int n) { L1: goto L2; L2: - goto L3; // expected-error {{illegal goto into protected scope}} + goto L3; // expected-error {{goto into protected scope}} int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}} L3: goto L4; diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp index dd70d9744a..cdc3868a7b 100644 --- a/test/SemaCXX/scope-check.cpp +++ b/test/SemaCXX/scope-check.cpp @@ -133,3 +133,21 @@ namespace test7 { return; } } + +// PR7789 +namespace test8 { + void test1(int c) { + switch (c) { + case 0: + int x = 56; // expected-note {{jump bypasses variable initialization}} + case 1: // expected-error {{switch case is in protected scope}} + x = 10; + } + } + + void test2() { + goto l2; // expected-error {{goto into protected scope}} + l1: int x = 5; // expected-note {{jump bypasses variable initialization}} + l2: x++; + } +} -- 2.40.0