diff options
author | Steve Naroff <snaroff@apple.com> | 2009-02-28 16:48:43 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-02-28 16:48:43 +0000 |
commit | d123bd05cab62bb3c641d0c2343fd94e6a96235e (patch) | |
tree | 710a9706402f096e1bed6df64d28b5e65dccab2c /clang/lib/Sema | |
parent | 638b836aab3e6df7a568913fad46fd70225a1d21 (diff) | |
download | bcm5719-llvm-d123bd05cab62bb3c641d0c2343fd94e6a96235e.tar.gz bcm5719-llvm-d123bd05cab62bb3c641d0c2343fd94e6a96235e.zip |
Fix <rdar://problem/6451399> problems with labels and blocks.
- Move the 'LabelMap' from Sema to Scope. To avoid layering problems, the second element is now a 'StmtTy *', which makes the LabelMap a bit more verbose to deal with.
- Add 'ActiveScope' to Sema. Managed by ActOnStartOfFunctionDef(), ObjCActOnStartOfMethodDef(), ActOnBlockStmtExpr().
- Changed ActOnLabelStmt(), ActOnGotoStmt(), ActOnAddrLabel(), and ActOnFinishFunctionBody() to use the new ActiveScope.
- Added FIXME to workaround in ActOnFinishFunctionBody() (for dealing with C++ nested functions).
llvm-svn: 65694
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 24 |
6 files changed, 64 insertions, 19 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2bb6a17ac10..57ed9884ba7 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -169,6 +169,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer) StdNamespace = 0; TUScope = 0; + ActiveScope = 0; + if (getLangOptions().CPlusPlus) FieldCollector.reset(new CXXFieldCollector()); diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index fe8176f62fc..1b6d6c14065 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -102,15 +102,14 @@ public: /// the active block object that represents it. BlockSemaInfo *CurBlock; + /// ActiveScope - If inside of a function, method, or block definition, + /// this contains a pointer to the active scope that represents it. + Scope *ActiveScope; + /// PackContext - Manages the stack for #pragma pack. An alignment /// of 0 indicates default alignment. void *PackContext; // Really a "PragmaPackStack*" - /// LabelMap - This is a mapping from label identifiers to the LabelStmt for - /// it (which acts like the label decl in some ways). Forward referenced - /// labels have a LabelStmt created for them with a null location & SubStmt. - llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap; - llvm::SmallVector<SwitchStmt*, 8> SwitchStack; /// ExtVectorDecls - This is a list all the extended vector types. This allows @@ -2070,6 +2069,10 @@ struct BlockSemaInfo { /// arguments etc. Scope *TheScope; + /// PrevFunctionScope - This is the scope for the enclosing function. + /// For global blocks, this will be null. + Scope *PrevFunctionScope; + /// ReturnType - This will get set to block result type, by looking at /// return types, if any, in the block body. Type *ReturnType; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e99be90963e..98b8dbc9c07 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2444,6 +2444,8 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) { Decl *decl = static_cast<Decl*>(D); FunctionDecl *FD = cast<FunctionDecl>(decl); + ActiveScope = FnBodyScope; + // See if this is a redefinition. const FunctionDecl *Definition; if (FD->getBody(Definition)) { @@ -2586,17 +2588,29 @@ Sema::DeclTy *Sema::ActOnFinishFunctionBody(DeclTy *D, StmtArg BodyArg) { return 0; } PopDeclContext(); + + // FIXME: Temporary hack to workaround nested C++ functions. For example: + // class C2 { + // void f() { + // class LC1 { + // int m() { return 1; } + // }; + // } + // }; + if (ActiveScope == 0) + return D; + // Verify and clean out per-function state. - bool HaveLabels = !LabelMap.empty(); + bool HaveLabels = !ActiveScope->LabelMap.empty(); // Check goto/label use. - for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator - I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) { + for (Scope::LabelMapTy::iterator I = ActiveScope->LabelMap.begin(), + E = ActiveScope->LabelMap.end(); I != E; ++I) { // Verify that we have no forward references left. If so, there was a goto // or address of a label taken, but no definition of it. Label fwd // definitions are indicated with a null substmt. - if (I->second->getSubStmt() == 0) { - LabelStmt *L = I->second; + LabelStmt *L = static_cast<LabelStmt*>(I->second); + if (L->getSubStmt() == 0) { // Emit error. Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName(); @@ -2618,7 +2632,8 @@ Sema::DeclTy *Sema::ActOnFinishFunctionBody(DeclTy *D, StmtArg BodyArg) { } } } - LabelMap.clear(); + // This reset is for both functions and methods. + ActiveScope = 0; if (!Body) return D; diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index dc30ac2ea90..cc867862552 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -36,6 +36,8 @@ void Sema::ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) { // Allow all of Sema to see that we are entering a method definition. PushDeclContext(FnBodyScope, MDecl); + ActiveScope = FnBodyScope; + // Create Decl objects for each parameter, entrring them in the scope for // binding to their use. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8604670d6ed..e34a22e039b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4204,13 +4204,20 @@ Sema::ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, IdentifierInfo *LabelII) { // Look up the record for this label identifier. - LabelStmt *&LabelDecl = LabelMap[LabelII]; + llvm::DenseMap<IdentifierInfo*, Action::StmtTy*>::iterator I = + ActiveScope->LabelMap.find(LabelII); + LabelStmt *LabelDecl; + // If we haven't seen this label yet, create a forward reference. It // will be validated and/or cleaned up in ActOnFinishFunctionBody. - if (LabelDecl == 0) + if (I == ActiveScope->LabelMap.end()) { LabelDecl = new (Context) LabelStmt(LabLoc, LabelII, 0); + ActiveScope->LabelMap.insert(std::make_pair(LabelII, LabelDecl)); + } else + LabelDecl = static_cast<LabelStmt *>(I->second); + // Create the AST node. The address of a label always has type 'void*'. return new (Context) AddrLabelExpr(OpLoc, LabLoc, LabelDecl, Context.getPointerType(Context.VoidTy)); @@ -4397,7 +4404,9 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) { // Add BSI to CurBlock. BSI->PrevBlockInfo = CurBlock; + BSI->PrevFunctionScope = ActiveScope; CurBlock = BSI; + ActiveScope = BlockScope; BSI->ReturnType = 0; BSI->TheScope = BlockScope; @@ -4492,6 +4501,8 @@ Sema::ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, StmtTy *body, PopDeclContext(); + ActiveScope = CurBlock->PrevFunctionScope; + // Pop off CurBlock, handle nested blocks. CurBlock = CurBlock->PrevBlockInfo; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 990e951c3b6..dfcb65a3532 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -165,12 +165,19 @@ Action::OwningStmtResult Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation ColonLoc, StmtArg subStmt) { Stmt *SubStmt = static_cast<Stmt*>(subStmt.release()); + // Look up the record for this label identifier. - LabelStmt *&LabelDecl = LabelMap[II]; + Scope::LabelMapTy::iterator I = ActiveScope->LabelMap.find(II); + LabelStmt *LabelDecl; + // If not forward referenced or defined already, just create a new LabelStmt. - if (LabelDecl == 0) - return Owned(LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt)); + if (I == ActiveScope->LabelMap.end()) { + LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt); + ActiveScope->LabelMap.insert(std::make_pair(II, LabelDecl)); + return Owned(LabelDecl); + } else + LabelDecl = static_cast<LabelStmt *>(I->second); assert(LabelDecl->getID() == II && "Label mismatch!"); @@ -672,11 +679,16 @@ Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, return StmtError(Diag(GotoLoc, diag::err_goto_in_block)); // Look up the record for this label identifier. - LabelStmt *&LabelDecl = LabelMap[LabelII]; + Scope::LabelMapTy::iterator I = ActiveScope->LabelMap.find(LabelII); - // If we haven't seen this label yet, create a forward reference. - if (LabelDecl == 0) + LabelStmt *LabelDecl; + + // If not forward referenced or defined already, just create a new LabelStmt. + if (I == ActiveScope->LabelMap.end()) { LabelDecl = new (Context) LabelStmt(LabelLoc, LabelII, 0); + ActiveScope->LabelMap.insert(std::make_pair(LabelII, LabelDecl)); + } else + LabelDecl = static_cast<LabelStmt *>(I->second); return Owned(new (Context) GotoStmt(LabelDecl, GotoLoc, LabelLoc)); } |