From 17a783055a41a44fda76b1747ebe6fd8ac2ba00a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 19 Apr 2009 05:28:12 +0000 Subject: [PATCH] run the jump checker on blocks, even though they don't have gotos, they do allow switches. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69510 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 4 ++++ lib/Sema/SemaExpr.cpp | 10 +++++++++- test/Sema/scope-check.c | 15 ++++++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index e8742e8e51..e4af8a5c46 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -107,6 +107,10 @@ struct BlockSemaInfo { /// block. llvm::SmallVector SwitchStack; + /// SavedFunctionNeedsScopeChecking - This is the value of + /// CurFunctionNeedsScopeChecking at the point when the block started. + bool SavedFunctionNeedsScopeChecking; + /// PrevBlockInfo - If this is nested inside another block, this points /// to the outer block. BlockSemaInfo *PrevBlockInfo; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d8e57f928d..3eeadce453 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4661,6 +4661,8 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) { BSI->ReturnType = 0; BSI->TheScope = BlockScope; BSI->hasBlockDeclRefExprs = false; + BSI->SavedFunctionNeedsScopeChecking = CurFunctionNeedsScopeChecking; + CurFunctionNeedsScopeChecking = false; BSI->TheDecl = BlockDecl::Create(Context, CurContext, CaretLoc); PushDeclContext(BlockScope, BSI->TheDecl); @@ -4746,11 +4748,12 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { // Ensure that CurBlock is deleted. llvm::OwningPtr CC(CurBlock); + CurFunctionNeedsScopeChecking = CurBlock->SavedFunctionNeedsScopeChecking; + // Pop off CurBlock, handle nested blocks. CurBlock = CurBlock->PrevBlockInfo; // FIXME: Delete the ParmVarDecl objects as well??? - } /// ActOnBlockStmtExpr - This is called when the body of a block statement @@ -4793,6 +4796,11 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BlockTy = Context.getBlockPointerType(BlockTy); + // If needed, diagnose invalid gotos and switches in the block. + if (CurFunctionNeedsScopeChecking) + DiagnoseInvalidJumps(static_cast(body.get())); + CurFunctionNeedsScopeChecking = BSI->SavedFunctionNeedsScopeChecking; + BSI->TheDecl->setBody(static_cast(body.release())); return Owned(new (Context) BlockExpr(BSI->TheDecl, BlockTy, BSI->hasBlockDeclRefExprs)); diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c index 59fd832dc6..76041c4916 100644 --- a/test/Sema/scope-check.c +++ b/test/Sema/scope-check.c @@ -164,9 +164,22 @@ L2: return; } +void test11(int n) { + void *P = ^{ + switch (n) { + case 1:; + 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}} + return; + } + }; +} + // TODO: When and if gotos are allowed in blocks, this should work. -void test13(int n) { +void test12(int n) { void *P = ^{ goto L1; // expected-error {{goto not allowed in block literal}} L1: -- 2.40.0