forked from OSchip/llvm-project
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. llvm-svn: 125771
This commit is contained in:
parent
50c3c1316a
commit
cab02a60d2
|
@ -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; }
|
||||
|
|
|
@ -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">,
|
||||
|
|
|
@ -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); // "({..})"
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) << " ";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -629,6 +629,9 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
|
|||
if (D->isUsed() || D->hasAttr<UnusedAttr>())
|
||||
return false;
|
||||
|
||||
if (isa<LabelDecl>(D))
|
||||
return true;
|
||||
|
||||
// White-list anything that isn't a local variable.
|
||||
if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
|
||||
!D->getDeclContext()->isFunctionOrMethod())
|
||||
|
@ -675,12 +678,15 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) {
|
|||
if (!ShouldDiagnoseUnusedDecl(D))
|
||||
return;
|
||||
|
||||
unsigned DiagID;
|
||||
if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable())
|
||||
Diag(D->getLocation(), diag::warn_unused_exception_param)
|
||||
<< D->getDeclName();
|
||||
DiagID = diag::warn_unused_exception_param;
|
||||
else if (isa<LabelDecl>(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) {
|
||||
|
|
|
@ -921,9 +921,9 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
}
|
||||
|
||||
if (!isa<VarDecl>(d) && !isa<ObjCIvarDecl>(d) && !isFunctionOrMethod(d) &&
|
||||
!isa<TypeDecl>(d)) {
|
||||
!isa<TypeDecl>(d) && !isa<LabelDecl>(d)) {
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
|
||||
<< Attr.getName() << 2 /*variable and function*/;
|
||||
<< Attr.getName() << 14 /*variable, function, labels*/;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -2168,8 +2168,9 @@ bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
|
|||
|
||||
llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
|
||||
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<LabelDecl>(D) && "declaration not instantiated in this scope");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Decl *, DeclArgumentPack *> *Found
|
||||
= CurrentInstantiationScope->findInstantiationOf(D);
|
||||
assert(Found);
|
||||
|
||||
if (Decl *FD = Found->dyn_cast<Decl *>())
|
||||
return cast<NamedDecl>(FD);
|
||||
if (Found) {
|
||||
if (Decl *FD = Found->dyn_cast<Decl *>())
|
||||
return cast<NamedDecl>(FD);
|
||||
|
||||
unsigned PackIdx = ArgumentPackSubstitutionIndex;
|
||||
return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[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<LabelDecl>(D));
|
||||
|
||||
unsigned PackIdx = ArgumentPackSubstitutionIndex;
|
||||
return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
|
||||
Decl *Inst = SubstDecl(D, CurContext, TemplateArgs);
|
||||
assert(Inst && "Failed to instantiate label??");
|
||||
|
||||
CurrentInstantiationScope->InstantiatedLocal(D, Inst);
|
||||
return cast<LabelDecl>(Inst);
|
||||
}
|
||||
|
||||
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
|
||||
|
|
|
@ -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<Derived>::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<LabelDecl>(LD), SourceLocation(),
|
||||
SubStmt.get());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
@ -4755,9 +4756,14 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
|
|||
template<typename Derived>
|
||||
StmtResult
|
||||
TreeTransform<Derived>::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<LabelDecl>(LD));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
@ -5798,8 +5804,13 @@ TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
|
|||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::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<LabelDecl>(LD));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
|
|
@ -725,7 +725,6 @@ void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
|
|||
|
||||
void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
|
||||
VisitNamedDecl(D);
|
||||
if (Record[Idx++]) D->setHasUnusedAttribute();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue