From: Chris Lattner Date: Thu, 17 Feb 2011 20:34:02 +0000 (+0000) Subject: Step #2/N of __label__ support: keep pushing LabelDecl forward, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=57ad37823e198f977cac605dbfbaefb4daf325e9;p=clang Step #2/N of __label__ support: keep pushing LabelDecl forward, making them be template instantiated in a more normal way and make them handle attributes like other decls. This fixes the used/unused label handling stuff, making it use the same infrastructure as other decls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125771 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index cca25cf73f..4da6204b69 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -296,10 +296,6 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, /// location of the statement. For GNU local labels (__label__), the decl /// location is where the __label__ is. class LabelDecl : public NamedDecl { - /// HasUnusedAttr - True if the label has __attribute__((unused)) on it. - /// FIXME: Just use attributes! - unsigned HasUnusedAttr : 1; - LabelStmt *TheStmt; LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S) : NamedDecl(Label, DC, L, II), TheStmt(S) {} @@ -311,9 +307,6 @@ public: LabelStmt *getStmt() const { return TheStmt; } void setStmt(LabelStmt *T) { TheStmt = T; } - bool hasUnusedAttribute() const { return HasUnusedAttr; } - void setHasUnusedAttribute() { HasUnusedAttr = true; } - // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LabelDecl *D) { return true; } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index e9df286d2d..7b28463349 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1068,7 +1068,8 @@ def warn_attribute_wrong_decl_type : Warning< "variables and functions|functions and methods|parameters|" "parameters and methods|functions, methods and blocks|" "classes and virtual methods|functions, methods, and parameters|" - "classes|virtual methods|class members|variables|methods}1">; + "classes|virtual methods|class members|variables|methods|" + "variables, functions and labels}1">; def err_attribute_wrong_decl_type : Error< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" @@ -1094,8 +1095,6 @@ def err_cconv_varargs : Error< def err_regparm_mismatch : Error<"function declared with with regparm(%0) " "attribute was previously declared " "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">; -def warn_label_attribute_not_unused : Warning< - "the only valid attribute for labels is 'unused'">; def warn_impcast_vector_scalar : Warning< "implicit conversion turns vector to scalar: %0 to %1">, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 98328479c4..74807611f3 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1717,10 +1717,10 @@ public: Stmt *SubStmt, Scope *CurScope); StmtResult ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation ColonLoc, Stmt *SubStmt, - const AttributeList *Attr); - StmtResult ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, - SourceLocation ColonLoc, Stmt *SubStmt, - bool HasUnusedAttr); + AttributeList *Attr); + StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, + SourceLocation ColonLoc, Stmt *SubStmt); + StmtResult ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *ThenVal, @@ -1753,6 +1753,9 @@ public: StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, IdentifierInfo *LabelII); + StmtResult ActOnGotoStmt(SourceLocation GotoLoc, + SourceLocation LabelLoc, + LabelDecl *TheDecl); StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, Expr *DestExp); @@ -2078,7 +2081,10 @@ public: ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, IdentifierInfo *LabelII); - + ExprResult ActOnAddrLabel(SourceLocation OpLoc, + SourceLocation LabLoc, + LabelDecl *LD); + ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, SourceLocation RPLoc); // "({..})" diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index ce670315e2..53f4a9d8c8 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -332,6 +332,7 @@ namespace clang { // declarations with automatically-generated ones from // clang/AST/DeclNodes.inc. Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); + Decl *VisitLabelDecl(LabelDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); Decl *VisitTypedefDecl(TypedefDecl *D); diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 30c9d8497c..77b4257470 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -51,6 +51,7 @@ namespace { void VisitFunctionDecl(FunctionDecl *D); void VisitFieldDecl(FieldDecl *D); void VisitVarDecl(VarDecl *D); + void VisitLabelDecl(LabelDecl *D); void VisitParmVarDecl(ParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); @@ -537,6 +538,11 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) { } } +void DeclPrinter::VisitLabelDecl(LabelDecl *D) { + Out << D->getNameAsString() << ":"; +} + + void DeclPrinter::VisitVarDecl(VarDecl *D) { if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None) Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " "; diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 2e7f72f81c..049267ae36 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -61,8 +61,7 @@ bool FunctionScopeInfo::checkLabelUse(Stmt *Body, Sema &S) { // 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(); + S.DiagnoseUnusedDecl(L); continue; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index bcec9d4839..98555d9525 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -629,6 +629,9 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { if (D->isUsed() || D->hasAttr()) return false; + if (isa(D)) + return true; + // White-list anything that isn't a local variable. if (!isa(D) || isa(D) || isa(D) || !D->getDeclContext()->isFunctionOrMethod()) @@ -675,12 +678,15 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { if (!ShouldDiagnoseUnusedDecl(D)) return; + unsigned DiagID; if (isa(D) && cast(D)->isExceptionVariable()) - Diag(D->getLocation(), diag::warn_unused_exception_param) - << D->getDeclName(); + DiagID = diag::warn_unused_exception_param; + else if (isa(D)) + DiagID = diag::warn_unused_label; else - Diag(D->getLocation(), diag::warn_unused_variable) - << D->getDeclName(); + DiagID = diag::warn_unused_variable; + + Diag(D->getLocation(), DiagID) << D->getDeclName(); } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index b0636bcb96..54e9405cba 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -921,9 +921,9 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { } if (!isa(d) && !isa(d) && !isFunctionOrMethod(d) && - !isa(d)) { + !isa(d) && !isa(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 2 /*variable and function*/; + << Attr.getName() << 14 /*variable, function, labels*/; return; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4bba240231..6892424e09 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8362,7 +8362,11 @@ ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, // 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*'. return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl, diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 2b323ef4b4..f31fbe2406 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -234,26 +234,7 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, StmtResult Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation ColonLoc, Stmt *SubStmt, - const AttributeList *Attr) { - // According to GCC docs, "the only attribute that makes sense after a label - // is 'unused'". - bool HasUnusedAttr = false; - for ( ; Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_unused) { - HasUnusedAttr = true; - } else { - Diag(Attr->getLoc(), diag::warn_label_attribute_not_unused); - Attr->setInvalid(true); - } - } - - return ActOnLabelStmt(IdentLoc, II, ColonLoc, SubStmt, HasUnusedAttr); -} - -StmtResult -Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, - SourceLocation ColonLoc, Stmt *SubStmt, - bool HasUnusedAttr) { + AttributeList *Attr) { // Look up the record for this label identifier. LabelDecl *&TheDecl = getCurFunction()->LabelMap[II]; @@ -263,6 +244,16 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *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) { + // If the label was multiply defined, reject it now. if (TheDecl->getStmt()) { Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName(); @@ -273,9 +264,6 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, // 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); @@ -1038,8 +1026,6 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, IdentifierInfo *LabelII) { - getCurFunction()->setHasBranchIntoScope(); - // Look up the record for this label identifier. LabelDecl *&TheDecl = getCurFunction()->LabelMap[LabelII]; @@ -1047,6 +1033,13 @@ Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, if (TheDecl == 0) TheDecl = LabelDecl::Create(Context, CurContext, LabelLoc, LabelII); + return ActOnGotoStmt(GotoLoc, LabelLoc, TheDecl); +} + +StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, + SourceLocation LabelLoc, + LabelDecl *TheDecl) { + getCurFunction()->setHasBranchIntoScope(); TheDecl->setUsed(); return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc)); } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 41e44ad6d1..44f5913d55 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2168,8 +2168,9 @@ bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, llvm::PointerUnion * LocalInstantiationScope::findInstantiationOf(const Decl *D) { - for (LocalInstantiationScope *Current = this; Current; + for (LocalInstantiationScope *Current = this; Current; Current = Current->Outer) { + // Check if we found something within this scope. const Decl *CheckD = D; do { @@ -2189,8 +2190,11 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) { if (!Current->CombineWithOuterScope) break; } - - assert(0 && "declaration was not instantiated in this scope!"); + + // If we didn't find the decl, then we either have a sema bug, or we have a + // forward reference to a label declaration. Return null to indicate that + // we have an uninstantiated label. + assert(isa(D) && "declaration not instantiated in this scope"); return 0; } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9197b50330..ecb9019136 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -100,6 +100,14 @@ TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { return D; } +Decl * +TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { + LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier()); + Owner->addDecl(Inst); + return Inst; +} + Decl * TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) { assert(false && "Namespaces cannot be instantiated"); @@ -2863,13 +2871,24 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; llvm::PointerUnion *Found = CurrentInstantiationScope->findInstantiationOf(D); - assert(Found); - if (Decl *FD = Found->dyn_cast()) - return cast(FD); + if (Found) { + if (Decl *FD = Found->dyn_cast()) + return cast(FD); + + unsigned PackIdx = ArgumentPackSubstitutionIndex; + return cast((*Found->get())[PackIdx]); + } + + // If we didn't find the decl, then we must have a label decl that hasn't + // been found yet. Lazily instantiate it and return it now. + assert(isa(D)); + + Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); + assert(Inst && "Failed to instantiate label??"); - unsigned PackIdx = ArgumentPackSubstitutionIndex; - return cast((*Found->get())[PackIdx]); + CurrentInstantiationScope->InstantiatedLocal(D, Inst); + return cast(Inst); } if (CXXRecordDecl *Record = dyn_cast(D)) { diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 1fc36754df..913edaa68d 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1,15 +1,16 @@ -//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===/ +//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===/ +//===----------------------------------------------------------------------===// // // This file implements a semantic tree transformation that takes a given // AST and rebuilds it, possibly transforming some nodes in the process. // -//===----------------------------------------------------------------------===/ +//===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H #define LLVM_CLANG_SEMA_TREETRANSFORM_H @@ -975,11 +976,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) { - return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, SubStmt, - HasUnusedAttr); + StmtResult RebuildLabelStmt(SourceLocation IdentLoc, LabelDecl *L, + SourceLocation ColonLoc, Stmt *SubStmt) { + return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt); } /// \brief Build a new "if" statement. @@ -987,8 +986,8 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond, - VarDecl *CondVar, Stmt *Then, - SourceLocation ElseLoc, Stmt *Else) { + VarDecl *CondVar, Stmt *Then, + SourceLocation ElseLoc, Stmt *Else) { return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then, ElseLoc, Else); } @@ -997,7 +996,7 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc, - Expr *Cond, VarDecl *CondVar) { + Expr *Cond, VarDecl *CondVar) { return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond, CondVar); } @@ -1007,7 +1006,7 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildSwitchStmtBody(SourceLocation SwitchLoc, - Stmt *Switch, Stmt *Body) { + Stmt *Switch, Stmt *Body) { return getSema().ActOnFinishSwitchStmt(SwitchLoc, Switch, Body); } @@ -1015,10 +1014,8 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildWhileStmt(SourceLocation WhileLoc, - Sema::FullExprArg Cond, - VarDecl *CondVar, - Stmt *Body) { + StmtResult RebuildWhileStmt(SourceLocation WhileLoc, Sema::FullExprArg Cond, + VarDecl *CondVar, Stmt *Body) { return getSema().ActOnWhileStmt(WhileLoc, Cond, CondVar, Body); } @@ -1051,7 +1048,7 @@ public: /// Subclasses may override this routine to provide different behavior. StmtResult RebuildGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *Label) { - return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label->getIdentifier()); + return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label); } /// \brief Build a new indirect goto statement. @@ -1543,7 +1540,7 @@ public: /// Subclasses may override this routine to provide different behavior. ExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc, SourceLocation LabelLoc, LabelDecl *Label) { - return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc,Label->getIdentifier()); + return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label); } /// \brief Build a new GNU statement expression. @@ -4511,12 +4508,16 @@ TreeTransform::TransformLabelStmt(LabelStmt *S) { if (SubStmt.isInvalid()) return StmtError(); + Decl *LD = getDerived().TransformDecl(S->getDecl()->getLocation(), + S->getDecl()); + if (!LD) + return StmtError(); + + // FIXME: Pass the real colon location in. - SourceLocation ColonLoc = SemaRef.PP.getLocForEndOfToken(S->getIdentLoc()); return getDerived().RebuildLabelStmt(S->getIdentLoc(), - S->getDecl()->getIdentifier(), ColonLoc, - SubStmt.get(), - S->getDecl()->hasUnusedAttribute()); + cast(LD), SourceLocation(), + SubStmt.get()); } template @@ -4755,9 +4756,14 @@ TreeTransform::TransformForStmt(ForStmt *S) { template StmtResult TreeTransform::TransformGotoStmt(GotoStmt *S) { + Decl *LD = getDerived().TransformDecl(S->getLabel()->getLocation(), + S->getLabel()); + if (!LD) + return StmtError(); + // Goto statements must always be rebuilt, to resolve the label. return getDerived().RebuildGotoStmt(S->getGotoLoc(), S->getLabelLoc(), - S->getLabel()); + cast(LD)); } template @@ -5798,8 +5804,13 @@ TreeTransform::TransformParenListExpr(ParenListExpr *E) { template ExprResult TreeTransform::TransformAddrLabelExpr(AddrLabelExpr *E) { + Decl *LD = getDerived().TransformDecl(E->getLabel()->getLocation(), + E->getLabel()); + if (!LD) + return ExprError(); + return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(), - E->getLabel()); + cast(LD)); } template diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 27e771804c..dec15dd694 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -725,7 +725,6 @@ void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { void ASTDeclReader::VisitLabelDecl(LabelDecl *D) { VisitNamedDecl(D); - if (Record[Idx++]) D->setHasUnusedAttribute(); } diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index dd43e1a05d..ce07e1389b 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -654,7 +654,6 @@ void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { VisitNamedDecl(D); - Record.push_back(D->hasUnusedAttribute()); Code = serialization::DECL_LABEL; } diff --git a/test/Sema/warn-unused-label.c b/test/Sema/warn-unused-label.c index 03be7da2fc..48370a5fd6 100644 --- a/test/Sema/warn-unused-label.c +++ b/test/Sema/warn-unused-label.c @@ -4,8 +4,8 @@ void f() { a: goto a; b: // expected-warning{{unused}} - c: __attribute__((unused)); // expected-warning {{unused label 'c'}} - d: __attribute__((noreturn)); // expected-warning {{the only valid attribute for labels is 'unused'}} + c: __attribute__((unused)); + d: __attribute__((noreturn)); // expected-warning {{'noreturn' attribute only applies to functions}} goto d; return; }