aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2011-02-18 01:27:55 +0000
committerChris Lattner <sabre@nondot.org>2011-02-18 01:27:55 +0000
commit337e550218128e7d922c09bb354fbc71de90c568 (patch)
treead1699cd2931e9dcb944ffe6ee620db7727c8ccc
parent380ebecb32993bf0426e25519eb78d7816b74b12 (diff)
Switch labels over to using normal name lookup, instead of their
own weird little DenseMap. Hey look, we now emit unused label warnings deterministically, amazing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125813 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Scope.h5
-rw-r--r--include/clang/Sema/ScopeInfo.h10
-rw-r--r--include/clang/Sema/Sema.h16
-rw-r--r--lib/Parse/ParseExpr.cpp5
-rw-r--r--lib/Parse/ParseStmt.cpp17
-rw-r--r--lib/Sema/Sema.cpp49
-rw-r--r--lib/Sema/SemaDecl.cpp19
-rw-r--r--lib/Sema/SemaDeclObjC.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp29
-rw-r--r--lib/Sema/SemaLookup.cpp35
-rw-r--r--lib/Sema/SemaStmt.cpp37
11 files changed, 72 insertions, 151 deletions
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h
index ad3ad4df13..d7fda35cdb 100644
--- a/include/clang/Sema/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -53,7 +53,7 @@ public:
/// ClassScope - The scope of a struct/union/class definition.
ClassScope = 0x20,
- /// BlockScope - This is a scope that corresponds to a block object.
+ /// BlockScope - This is a scope that corresponds to a block/closure object.
/// Blocks serve as top-level scopes for some objects like labels, they
/// also prevent things like break and continue. BlockScopes always have
/// the FnScope, BreakScope, ContinueScope, and DeclScope flags set as well.
@@ -146,8 +146,7 @@ public:
unsigned getFlags() const { return Flags; }
void setFlags(unsigned F) { Flags = F; }
- /// isBlockScope - Return true if this scope does not correspond to a
- /// closure.
+ /// isBlockScope - Return true if this scope correspond to a closure.
bool isBlockScope() const { return Flags & BlockScope; }
/// getParent - Return the scope that this is nested in.
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index 6a0d54d150..b0bb95509a 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -52,11 +52,6 @@ public:
/// \brief Used to determine if errors occurred in this function or block.
DiagnosticErrorTrap ErrorTrap;
- /// LabelMap - This is a mapping from label identifiers to the LabelDecl for
- /// it. Forward referenced labels have a LabelDecl created for them with a
- /// null statement.
- llvm::DenseMap<IdentifierInfo*, LabelDecl*> LabelMap;
-
/// SwitchStack - This is the current set of active switch statements in the
/// block.
llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
@@ -92,11 +87,6 @@ public:
virtual ~FunctionScopeInfo();
- /// checkLabelUse - This checks to see if any labels are used without being
- /// defined, emiting errors and returning true if any are found. This also
- /// warns about unused labels.
- bool checkLabelUse(Stmt *Body, Sema &S);
-
/// \brief Clear out the information in this function scope, making it
/// suitable for reuse.
void Clear();
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 3bb81d4c9b..48f3e90ee1 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1344,6 +1344,8 @@ public:
/// Tag name lookup, which finds the names of enums, classes,
/// structs, and unions.
LookupTagName,
+ /// Label name lookup.
+ LookupLabel,
/// Member name lookup, which finds the names of
/// class/struct/union members.
LookupMemberName,
@@ -1412,6 +1414,8 @@ public:
QualType T1, QualType T2,
UnresolvedSetImpl &Functions);
+ LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc);
+
DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
@@ -1715,9 +1719,6 @@ public:
StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
SourceLocation ColonLoc,
Stmt *SubStmt, Scope *CurScope);
- StmtResult ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
- SourceLocation ColonLoc, Stmt *SubStmt,
- AttributeList *Attr);
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
SourceLocation ColonLoc, Stmt *SubStmt);
@@ -1752,9 +1753,6 @@ public:
StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
- IdentifierInfo *LabelII);
- StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
- SourceLocation LabelLoc,
LabelDecl *TheDecl);
StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
SourceLocation StarLoc,
@@ -2078,11 +2076,7 @@ public:
Expr *Cond, Expr *LHS, Expr *RHS);
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
- ExprResult ActOnAddrLabel(SourceLocation OpLoc,
- SourceLocation LabLoc,
- IdentifierInfo *LabelII);
- ExprResult ActOnAddrLabel(SourceLocation OpLoc,
- SourceLocation LabLoc,
+ ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
LabelDecl *LD);
ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 7a6ec5923c..84d77300eb 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -795,8 +795,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError(Diag(Tok, diag::err_expected_ident));
Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
- Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(),
- Tok.getIdentifierInfo());
+ LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
+ Tok.getLocation());
+ Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD);
ConsumeToken();
return move(Res);
}
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 3e7ec533bd..2c4ab655ae 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -236,10 +236,14 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
// Broken substmt shouldn't prevent the label from being added to the AST.
if (SubStmt.isInvalid())
SubStmt = Actions.ActOnNullStmt(ColonLoc);
-
- return Actions.ActOnLabelStmt(IdentTok.getLocation(),
- IdentTok.getIdentifierInfo(),
- ColonLoc, SubStmt.get(), attrs.getList());
+
+ LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
+ IdentTok.getLocation());
+ if (AttributeList *Attrs = attrs.getList())
+ Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
+
+ return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
+ SubStmt.get());
}
/// ParseCaseStatement
@@ -1168,8 +1172,9 @@ StmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) {
StmtResult Res;
if (Tok.is(tok::identifier)) {
- Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
- Tok.getIdentifierInfo());
+ LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
+ Tok.getLocation());
+ Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
ConsumeToken();
} else if (Tok.is(tok::star)) {
// GNU indirect goto extension.
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index be78024031..7eb1c57412 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -45,60 +45,11 @@ void FunctionScopeInfo::Clear() {
HasBranchIntoScope = false;
HasIndirectGoto = false;
- LabelMap.clear();
SwitchStack.clear();
Returns.clear();
ErrorTrap.reset();
}
-bool FunctionScopeInfo::checkLabelUse(Stmt *Body, Sema &S) {
- bool AnyErrors = false;
- // FIXME: The iteration order of this (and thus, the order of errors and
- // warnings produced) is nondeterminstic.
- 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) {
- S.DiagnoseUnusedDecl(L);
- 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 98555d9525..95ab5fadd5 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -674,6 +674,8 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
return true;
}
+/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used
+/// unless they are marked attr(unused).
void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
if (!ShouldDiagnoseUnusedDecl(D))
return;
@@ -689,6 +691,14 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
Diag(D->getLocation(), DiagID) << D->getDeclName();
}
+static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
+ // 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)
+ S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
+}
+
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
@@ -708,6 +718,10 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (!S->hasErrorOccurred())
DiagnoseUnusedDecl(D);
+ // If this was a forward reference to a label, verify it was defined.
+ if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
+ CheckPoppedLabel(LD, *this);
+
// Remove this name from our lexical scope.
IdResolver.RemoveDecl(D);
}
@@ -5480,11 +5494,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
}
// Verify and clean out per-function state.
-
- // Check goto/label use.
- FunctionScopeInfo *CurFn = getCurFunction();
- CurFn->checkLabelUse(Body, *this);
-
if (Body) {
// C++ constructors that have function-try-blocks can't have return
// statements in the handlers of that block. (C++ [except.handle]p14)
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 102289b032..66f6f2b960 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1710,7 +1710,6 @@ Decl *Sema::ActOnMethodDeclaration(
// Make sure we can establish a context for the method.
if (!ClassDecl) {
Diag(MethodLoc, diag::error_missing_method_context);
- getCurFunction()->LabelMap.clear();
return 0;
}
QualType resultDeclType;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 6d339fd97c..2b1b8b2905 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1566,8 +1566,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
Name.getCXXNameType()->isDependentType()) {
DependentID = true;
} else if (SS.isSet()) {
- DeclContext *DC = computeDeclContext(SS, false);
- if (DC) {
+ if (DeclContext *DC = computeDeclContext(SS, false)) {
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
} else {
@@ -1575,10 +1574,10 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
}
}
- if (DependentID) {
+ if (DependentID)
return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand,
TemplateArgs);
- }
+
bool IvarLookupFollowUp = false;
// Perform the required lookup.
LookupResult R(*this, NameInfo, LookupOrdinaryName);
@@ -1613,9 +1612,10 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
if (E.isInvalid())
return ExprError();
- Expr *Ex = E.takeAs<Expr>();
- if (Ex) return Owned(Ex);
- // Synthesize ivars lazily
+ if (Expr *Ex = E.takeAs<Expr>())
+ return Owned(Ex);
+
+ // Synthesize ivars lazily.
if (getLangOptions().ObjCDefaultSynthProperties &&
getLangOptions().ObjCNonFragileABI2) {
if (SynthesizeProvisionalIvar(*this, R, II, NameLoc)) {
@@ -8354,18 +8354,6 @@ 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) {
- // 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. It
- // will be validated and/or cleaned up in ActOnFinishFunctionBody.
- if (TheDecl == 0)
- TheDecl = LabelDecl::Create(Context, CurContext, LabLoc, LabelII);
- return ActOnAddrLabel(OpLoc, LabLoc, TheDecl);
-}
-
-ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
LabelDecl *TheDecl) {
TheDecl->setUsed();
// Create the AST node. The address of a label always has type 'void*'.
@@ -8866,9 +8854,6 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
if (getCurFunction()->NeedsScopeChecking() && !hasAnyErrorsInThisFunction())
DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
- // Check goto/label use.
- BSI->checkLabelUse(Body, *this);
-
BSI->TheDecl->setBody(cast<CompoundStmt>(Body));
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 68eccfc280..b7740bf5c0 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -210,7 +210,8 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
IDNS = Decl::IDNS_Ordinary;
if (CPlusPlus) {
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace;
- if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
+ if (Redeclaration)
+ IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
}
break;
@@ -236,7 +237,10 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
IDNS = Decl::IDNS_Tag;
}
break;
-
+ case Sema::LookupLabel:
+ IDNS = Decl::IDNS_Label;
+ break;
+
case Sema::LookupMemberName:
IDNS = Decl::IDNS_Member;
if (CPlusPlus)
@@ -270,8 +274,7 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
}
void LookupResult::configure() {
- IDNS = getIDNS(LookupKind,
- SemaRef.getLangOptions().CPlusPlus,
+ IDNS = getIDNS(LookupKind, SemaRef.getLangOptions().CPlusPlus,
isForRedeclaration());
// If we're looking for one of the allocation or deallocation
@@ -1059,7 +1062,6 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (!getLangOptions().CPlusPlus) {
// Unqualified name lookup in C/Objective-C is purely lexical, so
// search in the declarations attached to the name.
-
if (NameKind == Sema::LookupRedeclarationWithLinkage) {
// Find the nearest non-transparent declaration scope.
while (!(S->getFlags() & Scope::DeclScope) ||
@@ -1392,6 +1394,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
case LookupOperatorName:
case LookupNamespaceName:
case LookupObjCProtocolName:
+ case LookupLabel:
// These lookups will never find a member in a C++ class (or base class).
return false;
@@ -2757,9 +2760,27 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
/*InBaseClass=*/false, Consumer, Visited);
}
-//----------------------------------------------------------------------------
+LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc) {
+ // Do a lookup to see if we have a label with this name already.
+ NamedDecl *Res = LookupSingleName(CurScope, II, Loc, LookupLabel,
+ NotForRedeclaration);
+ // If we found a label, check to see if it is in the same context as us. When
+ // in a Block, we don't want to reuse a label in an enclosing function.
+ if (Res && Res->getDeclContext() != CurContext)
+ Res = 0;
+
+ if (Res == 0) {
+ // If not forward referenced or defined already, create the backing decl.
+ Res = LabelDecl::Create(Context, CurContext, Loc, II);
+ PushOnScopeChains(Res, CurScope->getFnParent(), true);
+ }
+
+ return cast<LabelDecl>(Res);
+}
+
+//===----------------------------------------------------------------------===//
// Typo correction
-//----------------------------------------------------------------------------
+//===----------------------------------------------------------------------===//
namespace {
class TypoCorrectionConsumer : public VisibleDeclConsumer {
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index f31fbe2406..ba50824c1b 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -48,9 +48,8 @@ StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, bool LeadingEmptyMacro) {
return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacro));
}
-StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
+StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
// If we have an invalid decl, just return an error.
@@ -232,25 +231,6 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
}
StmtResult
-Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
- SourceLocation ColonLoc, Stmt *SubStmt,
- AttributeList *Attr) {
- // Look up the record for this label identifier.
- LabelDecl *&TheDecl = getCurFunction()->LabelMap[II];
-
- // If not forward referenced or defined already, create the backing decl.
- if (TheDecl == 0)
- TheDecl = LabelDecl::Create(Context, CurContext, IdentLoc, II);
-
- assert(TheDecl->getIdentifier() == II && "Label mismatch!");
-
- if (Attr)
- ProcessDeclAttributeList(CurScope, TheDecl, Attr);
-
- return ActOnLabelStmt(IdentLoc, TheDecl, ColonLoc, SubStmt);
-}
-
-StmtResult
Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
SourceLocation ColonLoc, Stmt *SubStmt) {
@@ -1023,19 +1003,6 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
ForLoc, RParenLoc));
}
-StmtResult
-Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
- IdentifierInfo *LabelII) {
- // 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 (TheDecl == 0)
- TheDecl = LabelDecl::Create(Context, CurContext, LabelLoc, LabelII);
-
- return ActOnGotoStmt(GotoLoc, LabelLoc, TheDecl);
-}
-
StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelDecl *TheDecl) {