From 337e550218128e7d922c09bb354fbc71de90c568 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 18 Feb 2011 01:27:55 +0000 Subject: [PATCH] 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 --- include/clang/Sema/Scope.h | 5 ++-- include/clang/Sema/ScopeInfo.h | 10 ------- include/clang/Sema/Sema.h | 16 ++++------- lib/Parse/ParseExpr.cpp | 5 ++-- lib/Parse/ParseStmt.cpp | 17 +++++++----- lib/Sema/Sema.cpp | 49 ---------------------------------- lib/Sema/SemaDecl.cpp | 19 +++++++++---- lib/Sema/SemaDeclObjC.cpp | 1 - lib/Sema/SemaExpr.cpp | 29 +++++--------------- lib/Sema/SemaLookup.cpp | 35 +++++++++++++++++++----- lib/Sema/SemaStmt.cpp | 37 ++----------------------- 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 LabelMap; - /// SwitchStack - This is the current set of active switch statements in the /// block. llvm::SmallVector 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); @@ -1750,9 +1751,6 @@ public: Stmt *First, Expr *Second, SourceLocation RParenLoc, Stmt *Body); - StmtResult ActOnGotoStmt(SourceLocation GotoLoc, - SourceLocation LabelLoc, - IdentifierInfo *LabelII); StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl); @@ -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::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(Body) ? - cast(Body)->getTryBlock() : - cast(Body); - llvm::SmallVector 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) <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(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(); - if (Ex) return Owned(Ex); - // Synthesize ivars lazily + if (Expr *Ex = E.takeAs()) + return Owned(Ex); + + // Synthesize ivars lazily. if (getLangOptions().ObjCDefaultSynthProperties && getLangOptions().ObjCNonFragileABI2) { if (SynthesizeProvisionalIvar(*this, R, II, NameLoc)) { @@ -8353,18 +8353,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(); @@ -8866,9 +8854,6 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (getCurFunction()->NeedsScopeChecking() && !hasAnyErrorsInThisFunction()) DiagnoseInvalidJumps(cast(Body)); - // Check goto/label use. - BSI->checkLabelUse(Body, *this); - BSI->TheDecl->setBody(cast(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(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(); // If we have an invalid decl, just return an error. @@ -231,25 +230,6 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, return Owned(DS); } -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) { -- 2.40.0