diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Decl.cpp | 6 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 3 | ||||
-rw-r--r-- | lib/AST/Stmt.cpp | 4 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 6 | ||||
-rw-r--r-- | lib/Analysis/CFG.cpp | 25 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 18 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 11 | ||||
-rw-r--r-- | lib/Sema/JumpDiagnostics.cpp | 42 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 48 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 41 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 34 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 50 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 51 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 66 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 10 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 11 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 8 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 21 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ExprEngine.cpp | 8 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SVals.cpp | 2 |
22 files changed, 200 insertions, 269 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index fded8ff38c..441444da9e 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2182,6 +2182,12 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { return new (C) TranslationUnitDecl(C); } +LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *II) { + return new (C) LabelDecl(DC, L, II, 0); +} + + NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id) { return new (C) NamespaceDecl(DC, L, Id); diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 110de64d8c..dfc5a6ae5d 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -269,7 +269,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCMethod: case ObjCProperty: return IDNS_Ordinary; - + case Label: + return IDNS_Label; case IndirectField: return IDNS_Ordinary | IDNS_Member; diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 66182957d6..7e73f02e67 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -161,7 +161,7 @@ void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) { } const char *LabelStmt::getName() const { - return getID()->getNameStart(); + return getDecl()->getIdentifier()->getNameStart(); } // This is defined here to avoid polluting Stmt.h with importing Expr.h @@ -658,7 +658,7 @@ void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) { } // IndirectGotoStmt -LabelStmt *IndirectGotoStmt::getConstantTarget() { +LabelDecl *IndirectGotoStmt::getConstantTarget() { if (AddrLabelExpr *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts())) return E->getLabel(); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index b96ffe8a48..2ffb807abc 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -101,7 +101,7 @@ void StmtProfiler::VisitDefaultStmt(DefaultStmt *S) { void StmtProfiler::VisitLabelStmt(LabelStmt *S) { VisitStmt(S); - VisitName(S->getID()); + VisitDecl(S->getDecl()); } void StmtProfiler::VisitIfStmt(IfStmt *S) { @@ -129,7 +129,7 @@ void StmtProfiler::VisitForStmt(ForStmt *S) { void StmtProfiler::VisitGotoStmt(GotoStmt *S) { VisitStmt(S); - VisitName(S->getLabel()->getID()); + VisitDecl(S->getLabel()); } void StmtProfiler::VisitIndirectGotoStmt(IndirectGotoStmt *S) { @@ -351,7 +351,7 @@ void StmtProfiler::VisitConditionalOperator(ConditionalOperator *S) { void StmtProfiler::VisitAddrLabelExpr(AddrLabelExpr *S) { VisitExpr(S); - VisitName(S->getLabel()->getID()); + VisitDecl(S->getLabel()); } void StmtProfiler::VisitStmtExpr(StmtExpr *S) { diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index d46b7e7830..6da4784405 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -242,7 +242,7 @@ class CFGBuilder { LocalScope::const_iterator ScopePos; // LabelMap records the mapping from Label expressions to their jump targets. - typedef llvm::DenseMap<LabelStmt*, JumpTarget> LabelMapTy; + typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy; LabelMapTy LabelMap; // A list of blocks that end with a "goto" that must be backpatched to their @@ -251,7 +251,7 @@ class CFGBuilder { BackpatchBlocksTy BackpatchBlocks; // A list of labels whose address has been taken (for indirect gotos). - typedef llvm::SmallPtrSet<LabelStmt*,5> LabelSetTy; + typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy; LabelSetTy AddressTakenLabels; bool badCFG; @@ -648,13 +648,13 @@ void CFGBuilder::addLocalScopeForStmt(Stmt* S) { LocalScope *Scope = 0; // For compound statement we will be creating explicit scope. - if (CompoundStmt* CS = dyn_cast<CompoundStmt>(S)) { + if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() ; BI != BE; ++BI) { - Stmt* SI = *BI; - if (LabelStmt* LS = dyn_cast<LabelStmt>(SI)) + Stmt *SI = *BI; + if (LabelStmt *LS = dyn_cast<LabelStmt>(SI)) SI = LS->getSubStmt(); - if (DeclStmt* DS = dyn_cast<DeclStmt>(SI)) + if (DeclStmt *DS = dyn_cast<DeclStmt>(SI)) Scope = addLocalScopeForDeclStmt(DS, Scope); } return; @@ -662,9 +662,9 @@ void CFGBuilder::addLocalScopeForStmt(Stmt* S) { // For any other statement scope will be implicit and as such will be // interesting only for DeclStmt. - if (LabelStmt* LS = dyn_cast<LabelStmt>(S)) + if (LabelStmt *LS = dyn_cast<LabelStmt>(S)) S = LS->getSubStmt(); - if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) + if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) addLocalScopeForDeclStmt(DS); } @@ -1454,16 +1454,17 @@ CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) { return VisitStmt(R, AddStmtChoice::AlwaysAdd); } -CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) { +CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt *L) { // Get the block of the labeled statement. Add it to our map. addStmt(L->getSubStmt()); - CFGBlock* LabelBlock = Block; + CFGBlock *LabelBlock = Block; if (!LabelBlock) // This can happen when the body is empty, i.e. LabelBlock = createBlock(); // scopes that only contains NullStmts. - assert(LabelMap.find(L) == LabelMap.end() && "label already in map"); - LabelMap[ L ] = JumpTarget(LabelBlock, ScopePos); + assert(LabelMap.find(L->getDecl()) == LabelMap.end() && + "label already in map"); + LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); // Labels partition blocks, so this is the end of the basic block we were // processing (L is the block's label). Because this is label (and we have diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 129416fa07..97dbf0ba31 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -70,7 +70,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Friend: case Decl::FriendTemplate: case Decl::Block: - + case Decl::Label: assert(0 && "Declaration not should not be in declstmts!"); case Decl::Function: // void X(); case Decl::Record: // struct/union/class X; diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index f782c8004a..f809c009ce 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -208,7 +208,7 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, // emitting them before we evaluate the subexpr. const Stmt *LastStmt = S.body_back(); while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) { - EmitLabel(*LS); + EmitLabel(LS->getDecl()); LastStmt = LS->getSubStmt(); } @@ -276,24 +276,24 @@ void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) { } CodeGenFunction::JumpDest -CodeGenFunction::getJumpDestForLabel(const LabelStmt *S) { - JumpDest &Dest = LabelMap[S]; +CodeGenFunction::getJumpDestForLabel(const LabelDecl *D) { + JumpDest &Dest = LabelMap[D]; if (Dest.isValid()) return Dest; // Create, but don't insert, the new block. - Dest = JumpDest(createBasicBlock(S->getName()), + Dest = JumpDest(createBasicBlock(D->getName()), EHScopeStack::stable_iterator::invalid(), NextCleanupDestIndex++); return Dest; } -void CodeGenFunction::EmitLabel(const LabelStmt &S) { - JumpDest &Dest = LabelMap[&S]; +void CodeGenFunction::EmitLabel(const LabelDecl *D) { + JumpDest &Dest = LabelMap[D]; // If we didn't need a forward reference to this label, just go // ahead and create a destination at the current scope. if (!Dest.isValid()) { - Dest = getJumpDestInCurrentScope(S.getName()); + Dest = getJumpDestInCurrentScope(D->getName()); // Otherwise, we need to give this label a target depth and remove // it from the branch-fixups list. @@ -311,7 +311,7 @@ void CodeGenFunction::EmitLabel(const LabelStmt &S) { void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { - EmitLabel(S); + EmitLabel(S.getDecl()); EmitStmt(S.getSubStmt()); } @@ -327,7 +327,7 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { - if (const LabelStmt *Target = S.getConstantTarget()) { + if (const LabelDecl *Target = S.getConstantTarget()) { EmitBranchThroughCleanup(getJumpDestForLabel(Target)); return; } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index ee8b98cdd4..b316fa86f1 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -668,7 +668,7 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) { Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, Align, false); } -llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) { +llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) { // Make sure that there is a block for the indirect goto. if (IndirectBranch == 0) GetIndirectGotoBlock(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index c4971506c5..adbc223afc 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -45,6 +45,7 @@ namespace clang { class CXXDestructorDecl; class CXXTryStmt; class Decl; + class LabelDecl; class EnumConstantDecl; class FunctionDecl; class FunctionProtoType; @@ -768,7 +769,7 @@ public: /// The given basic block lies in the current EH scope, but may be a /// target of a potentially scope-crossing jump; get a stable handle /// to which we can perform this jump later. - JumpDest getJumpDestInCurrentScope(const char *Name = 0) { + JumpDest getJumpDestInCurrentScope(llvm::StringRef Name = llvm::StringRef()) { return getJumpDestInCurrentScope(createBasicBlock(Name)); } @@ -887,7 +888,7 @@ private: DeclMapTy LocalDeclMap; /// LabelMap - This keeps track of the LLVM basic block for each C label. - llvm::DenseMap<const LabelStmt*, JumpDest> LabelMap; + llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap; // BreakContinueStack - This keeps track of where break and continue // statements should jump to. @@ -1168,7 +1169,7 @@ public: /// getBasicBlockForLabel - Return the LLVM basicblock that the specified /// label maps to. - JumpDest getJumpDestForLabel(const LabelStmt *S); + JumpDest getJumpDestForLabel(const LabelDecl *S); /// SimplifyForwardingBlocks - If the given basic block is only a branch to /// another basic block, simplify it. This assumes that no other code could @@ -1321,7 +1322,7 @@ public: /// the input field number being accessed. static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts); - llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L); + llvm::BlockAddress *GetAddrOfLabel(const LabelDecl *L); llvm::BasicBlock *GetIndirectGotoBlock(); /// EmitNullInitialization - Generate code to set a value of the given type to @@ -1504,7 +1505,7 @@ public: /// EmitLabel - Emit the block for the given label. It is legal to call this /// function even if there is no current insertion point. - void EmitLabel(const LabelStmt &S); // helper for EmitLabelStmt. + void EmitLabel(const LabelDecl *D); // helper for EmitLabelStmt. void EmitLabelStmt(const LabelStmt &S); void EmitGotoStmt(const GotoStmt &S); diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index bd6b48a30f..b73f0e9f14 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -62,7 +62,7 @@ class JumpScopeChecker { llvm::SmallVector<Stmt*, 16> Jumps; llvm::SmallVector<IndirectGotoStmt*, 4> IndirectJumps; - llvm::SmallVector<LabelStmt*, 4> IndirectJumpTargets; + llvm::SmallVector<LabelDecl*, 4> IndirectJumpTargets; public: JumpScopeChecker(Stmt *Body, Sema &S); private: @@ -71,7 +71,7 @@ private: void VerifyJumps(); void VerifyIndirectJumps(); void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope, - LabelStmt *Target, unsigned TargetScope); + LabelDecl *Target, unsigned TargetScope); void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc, unsigned JumpDiag); @@ -235,12 +235,12 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { // order to avoid blowing out the stack. while (true) { Stmt *Next; - if (isa<CaseStmt>(SubStmt)) - Next = cast<CaseStmt>(SubStmt)->getSubStmt(); - else if (isa<DefaultStmt>(SubStmt)) - Next = cast<DefaultStmt>(SubStmt)->getSubStmt(); - else if (isa<LabelStmt>(SubStmt)) - Next = cast<LabelStmt>(SubStmt)->getSubStmt(); + if (CaseStmt *CS = dyn_cast<CaseStmt>(SubStmt)) + Next = CS->getSubStmt(); + else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SubStmt)) + Next = DS->getSubStmt(); + else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt)) + Next = LS->getSubStmt(); else break; @@ -346,15 +346,15 @@ void JumpScopeChecker::VerifyJumps() { // With a goto, if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) { - CheckJump(GS, GS->getLabel(), GS->getGotoLoc(), + CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(), diag::err_goto_into_protected_scope); continue; } // We only get indirect gotos here when they have a constant target. if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) { - LabelStmt *Target = IGS->getConstantTarget(); - CheckJump(IGS, Target, IGS->getGotoLoc(), + LabelDecl *Target = IGS->getConstantTarget(); + CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(), diag::err_goto_into_protected_scope); continue; } @@ -424,15 +424,15 @@ void JumpScopeChecker::VerifyIndirectJumps() { // Collect a single representative of every scope containing a // label whose address was taken somewhere in the function. // For most code bases, there will be only one such scope. - llvm::DenseMap<unsigned, LabelStmt*> TargetScopes; - for (llvm::SmallVectorImpl<LabelStmt*>::iterator + llvm::DenseMap<unsigned, LabelDecl*> TargetScopes; + for (llvm::SmallVectorImpl<LabelDecl*>::iterator I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end(); I != E; ++I) { - LabelStmt *TheLabel = *I; - assert(LabelAndGotoScopes.count(TheLabel) && + LabelDecl *TheLabel = *I; + assert(LabelAndGotoScopes.count(TheLabel->getStmt()) && "Referenced label didn't get added to scopes?"); - unsigned LabelScope = LabelAndGotoScopes[TheLabel]; - LabelStmt *&Target = TargetScopes[LabelScope]; + unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()]; + LabelDecl *&Target = TargetScopes[LabelScope]; if (!Target) Target = TheLabel; } @@ -445,10 +445,10 @@ void JumpScopeChecker::VerifyIndirectJumps() { // entered, then verify that every jump scope can be trivially // exitted to reach a scope in S. llvm::BitVector Reachable(Scopes.size(), false); - for (llvm::DenseMap<unsigned,LabelStmt*>::iterator + for (llvm::DenseMap<unsigned,LabelDecl*>::iterator TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) { unsigned TargetScope = TI->first; - LabelStmt *TargetLabel = TI->second; + LabelDecl *TargetLabel = TI->second; Reachable.reset(); @@ -511,12 +511,12 @@ void JumpScopeChecker::VerifyIndirectJumps() { /// Diagnose an indirect jump which is known to cross scopes. void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump, unsigned JumpScope, - LabelStmt *Target, + LabelDecl *Target, unsigned TargetScope) { assert(JumpScope != TargetScope); S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); - S.Diag(Target->getIdentLoc(), diag::note_indirect_goto_target); + S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 8fbbeb85e3..2e7f72f81c 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -31,6 +31,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/AST/StmtCXX.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" @@ -50,6 +51,53 @@ void FunctionScopeInfo::Clear() { ErrorTrap.reset(); } +bool FunctionScopeInfo::checkLabelUse(Stmt *Body, Sema &S) { + bool AnyErrors = false; + for (llvm::DenseMap<IdentifierInfo*, LabelDecl*>::iterator + I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) { + LabelDecl *L = I->second; + + // 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 (L->getStmt() != 0) { + if (!L->isUsed()) + S.Diag(L->getLocation(), diag::warn_unused_label) << L->getDeclName(); + continue; + } + + AnyErrors = true; + + // Emit error. + S.Diag(L->getLocation(), diag::err_undeclared_label_use) << L->getDeclName(); + + // At this point, we have gotos that use the bogus label. Stitch it into + // the function body so that the AST is well formed. + if (Body == 0) { + // The whole function wasn't parsed correctly. + continue; + } + + // Otherwise, the body is valid: we want to stitch the label decl into the + // function somewhere so that it is properly owned and so that the goto + // has a valid target. Do this by creating LabelStmt and adding it to the + // end of the outer CompoundStmt. + LabelStmt *LS = new (S.Context) LabelStmt(L->getLocation(), L, + new (S.Context) NullStmt(L->getLocation())); + + CompoundStmt *Compound = isa<CXXTryStmt>(Body) ? + cast<CXXTryStmt>(Body)->getTryBlock() : + cast<CompoundStmt>(Body); + llvm::SmallVector<Stmt*, 64> Elements(Compound->body_begin(), + Compound->body_end()); + Elements.push_back(LS); + Compound->setStmts(S.Context, Elements.data(), Elements.size()); + } + return AnyErrors; +} + + + BlockScopeInfo::~BlockScopeInfo() { } void Sema::ActOnTranslationUnitScope(Scope *S) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2807e759b5..bcec9d4839 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5477,46 +5477,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, // Check goto/label use. FunctionScopeInfo *CurFn = getCurFunction(); - for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator - I = CurFn->LabelMap.begin(), E = CurFn->LabelMap.end(); I != E; ++I) { - LabelStmt *L = I->second; - - // 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 (L->getSubStmt() != 0) { - if (!L->isUsed()) - Diag(L->getIdentLoc(), diag::warn_unused_label) << L->getName(); - continue; - } - - // Emit error. - Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName(); - - // At this point, we have gotos that use the bogus label. Stitch it into - // the function body so that they aren't leaked and that the AST is well - // formed. - if (Body == 0) { - // The whole function wasn't parsed correctly. - continue; - } - - // Otherwise, the body is valid: we want to stitch the label decl into the - // function somewhere so that it is properly owned and so that the goto - // has a valid target. Do this by creating a new compound stmt with the - // label in it. - - // Give the label a sub-statement. - L->setSubStmt(new (Context) NullStmt(L->getIdentLoc())); - - CompoundStmt *Compound = isa<CXXTryStmt>(Body) ? - cast<CXXTryStmt>(Body)->getTryBlock() : - cast<CompoundStmt>(Body); - llvm::SmallVector<Stmt*, 64> Elements(Compound->body_begin(), - Compound->body_end()); - Elements.push_back(L); - Compound->setStmts(Context, Elements.data(), Elements.size()); - } + CurFn->checkLabelUse(Body, *this); if (Body) { // C++ constructors that have function-try-blocks can't have return diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0a95607975..94dd27d0c2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8321,20 +8321,19 @@ ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, } /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". -ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, - SourceLocation LabLoc, - IdentifierInfo *LabelII) { +ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, + IdentifierInfo *LabelII) { // Look up the record for this label identifier. - LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII]; + LabelDecl *&TheDecl = getCurFunction()->LabelMap[LabelII]; // 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) - LabelDecl = new (Context) LabelStmt(LabLoc, LabelII, 0); + if (TheDecl == 0) + TheDecl = LabelDecl::Create(Context, CurContext, LabLoc, LabelII); - LabelDecl->setUsed(); + TheDecl->setUsed(); // Create the AST node. The address of a label always has type 'void*'. - return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, LabelDecl, + return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl, Context.getPointerType(Context.VoidTy))); } @@ -8833,25 +8832,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BSI->TheDecl->setBody(cast<CompoundStmt>(Body)); - bool Good = true; // Check goto/label use. - for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator - I = BSI->LabelMap.begin(), E = BSI->LabelMap.end(); I != E; ++I) { - LabelStmt *L = I->second; - - // 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. - if (L->getSubStmt() != 0) { - if (!L->isUsed()) - Diag(L->getIdentLoc(), diag::warn_unused_label) << L->getName(); - continue; - } - - // Emit error. - Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName(); - Good = false; - } - if (!Good) { + if (BSI->checkLabelUse(0, *this)) { PopFunctionOrBlockScope(); return ExprError(); } diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index e5fd01ab70..2b323ef4b4 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -255,29 +255,31 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation ColonLoc, Stmt *SubStmt, bool HasUnusedAttr) { // Look up the record for this label identifier. - LabelStmt *&LabelDecl = getCurFunction()->LabelMap[II]; + LabelDecl *&TheDecl = getCurFunction()->LabelMap[II]; - // If not forward referenced or defined already, just create a new LabelStmt. - if (LabelDecl == 0) - return Owned(LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt, - HasUnusedAttr)); + // If not forward referenced or defined already, create the backing decl. + if (TheDecl == 0) + TheDecl = LabelDecl::Create(Context, CurContext, IdentLoc, II); - assert(LabelDecl->getID() == II && "Label mismatch!"); + assert(TheDecl->getIdentifier() == II && "Label mismatch!"); - // Otherwise, this label was either forward reference or multiply defined. If - // multiply defined, reject it now. - if (LabelDecl->getSubStmt()) { - Diag(IdentLoc, diag::err_redefinition_of_label) << LabelDecl->getID(); - Diag(LabelDecl->getIdentLoc(), diag::note_previous_definition); + // If the label was multiply defined, reject it now. + if (TheDecl->getStmt()) { + Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName(); + Diag(TheDecl->getLocation(), diag::note_previous_definition); return Owned(SubStmt); } - // Otherwise, this label was forward declared, and we just found its real - // definition. Fill in the forward definition and return it. - LabelDecl->setIdentLoc(IdentLoc); - LabelDecl->setSubStmt(SubStmt); - LabelDecl->setUnusedAttribute(HasUnusedAttr); - return Owned(LabelDecl); + // Otherwise, things are good. Fill in the declaration and return it. + TheDecl->setLocation(IdentLoc); + + // FIXME: Just use Decl ATTRIBUTES! + if (HasUnusedAttr) + TheDecl->setHasUnusedAttribute(); + LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); + TheDecl->setStmt(LS); + TheDecl->setLocation(IdentLoc); + return Owned(LS); } StmtResult @@ -1036,17 +1038,17 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, IdentifierInfo *LabelII) { - // Look up the record for this label identifier. - LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII]; - getCurFunction()->setHasBranchIntoScope(); + + // Look up the record for this label identifier. + LabelDecl *&TheDecl = getCurFunction()->LabelMap[LabelII]; // If we haven't seen this label yet, create a forward reference. - if (LabelDecl == 0) - LabelDecl = new (Context) LabelStmt(LabelLoc, LabelII, 0); + if (TheDecl == 0) + TheDecl = LabelDecl::Create(Context, CurContext, LabelLoc, LabelII); - LabelDecl->setUsed(); - return Owned(new (Context) GotoStmt(LabelDecl, GotoLoc, LabelLoc)); + TheDecl->setUsed(); + return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc)); } StmtResult diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index ca5d1c1ea0..cb0d4250fc 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -975,10 +975,9 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildLabelStmt(SourceLocation IdentLoc, - IdentifierInfo *Id, - SourceLocation ColonLoc, - Stmt *SubStmt, bool HasUnusedAttr) { + StmtResult RebuildLabelStmt(SourceLocation IdentLoc, IdentifierInfo *Id, + SourceLocation ColonLoc, Stmt *SubStmt, + bool HasUnusedAttr) { return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, SubStmt, HasUnusedAttr); } @@ -1028,10 +1027,8 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildDoStmt(SourceLocation DoLoc, Stmt *Body, - SourceLocation WhileLoc, - SourceLocation LParenLoc, - Expr *Cond, - SourceLocation RParenLoc) { + SourceLocation WhileLoc, SourceLocation LParenLoc, + Expr *Cond, SourceLocation RParenLoc) { return getSema().ActOnDoStmt(DoLoc, Body, WhileLoc, LParenLoc, Cond, RParenLoc); } @@ -1040,24 +1037,21 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildForStmt(SourceLocation ForLoc, - SourceLocation LParenLoc, - Stmt *Init, Sema::FullExprArg Cond, - VarDecl *CondVar, Sema::FullExprArg Inc, - SourceLocation RParenLoc, Stmt *Body) { + StmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *Init, Sema::FullExprArg Cond, + VarDecl *CondVar, Sema::FullExprArg Inc, + SourceLocation RParenLoc, Stmt *Body) { return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond, - CondVar, - Inc, RParenLoc, Body); + CondVar, Inc, RParenLoc, Body); } /// \brief Build a new goto statement. /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildGotoStmt(SourceLocation GotoLoc, - SourceLocation LabelLoc, - LabelStmt *Label) { - return getSema().ActOnGotoStmt(GotoLoc, Labe |