aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp6
-rw-r--r--lib/AST/DeclBase.cpp3
-rw-r--r--lib/AST/Stmt.cpp4
-rw-r--r--lib/AST/StmtProfile.cpp6
-rw-r--r--lib/Analysis/CFG.cpp25
-rw-r--r--lib/CodeGen/CGDecl.cpp2
-rw-r--r--lib/CodeGen/CGStmt.cpp18
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.h11
-rw-r--r--lib/Sema/JumpDiagnostics.cpp42
-rw-r--r--lib/Sema/Sema.cpp48
-rw-r--r--lib/Sema/SemaDecl.cpp41
-rw-r--r--lib/Sema/SemaExpr.cpp34
-rw-r--r--lib/Sema/SemaStmt.cpp50
-rw-r--r--lib/Sema/TreeTransform.h51
-rw-r--r--lib/Serialization/ASTReader.cpp66
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp10
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp11
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp8
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp21
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprEngine.cpp8
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp2
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