forked from OSchip/llvm-project
Don't warn for an unused label if it has 'unused' attribute. Fixes rdar://8483139.
llvm-svn: 114954
This commit is contained in:
parent
cd43c696c9
commit
9f48354b71
|
@ -562,10 +562,13 @@ class LabelStmt : public Stmt {
|
|||
Stmt *SubStmt;
|
||||
SourceLocation IdentLoc;
|
||||
bool Used : 1;
|
||||
bool HasUnusedAttr : 1;
|
||||
public:
|
||||
LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
|
||||
LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt,
|
||||
bool hasUnusedAttr = false)
|
||||
: Stmt(LabelStmtClass), Label(label),
|
||||
SubStmt(substmt), IdentLoc(IL), Used(false) {}
|
||||
SubStmt(substmt), IdentLoc(IL), Used(false),
|
||||
HasUnusedAttr(hasUnusedAttr) {}
|
||||
|
||||
// \brief Build an empty label statement.
|
||||
explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
|
||||
|
@ -580,10 +583,14 @@ public:
|
|||
void setSubStmt(Stmt *SS) { SubStmt = SS; }
|
||||
|
||||
/// \brief Whether this label was used.
|
||||
/// FIXME: Check "used" attribute (requires storing label attributes).
|
||||
bool isUsed() const { return Used; }
|
||||
bool isUsed(bool CheckUnusedAttr = true) const {
|
||||
return Used || (CheckUnusedAttr && HasUnusedAttr);
|
||||
}
|
||||
void setUsed(bool U = true) { Used = U; }
|
||||
|
||||
bool HasUnusedAttribute() const { return HasUnusedAttr; }
|
||||
void setUnusedAttribute(bool U) { HasUnusedAttr = U; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(IdentLoc, SubStmt->getLocEnd());
|
||||
}
|
||||
|
|
|
@ -962,6 +962,8 @@ def err_regparm_mismatch : Error<"function declared with with regparm(%0) "
|
|||
"attribute was previously declared %plural{0:without the regparm|1:"
|
||||
"with the regparm(1)|2:with the regparm(2)|3:with the regparm(3)|:with the"
|
||||
"regparm}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">,
|
||||
|
|
|
@ -1540,10 +1540,12 @@ public:
|
|||
StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
|
||||
SourceLocation ColonLoc,
|
||||
Stmt *SubStmt, Scope *CurScope);
|
||||
StmtResult ActOnLabelStmt(SourceLocation IdentLoc,
|
||||
IdentifierInfo *II,
|
||||
SourceLocation ColonLoc,
|
||||
Stmt *SubStmt);
|
||||
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);
|
||||
StmtResult ActOnIfStmt(SourceLocation IfLoc,
|
||||
FullExprArg CondVal, Decl *CondVar,
|
||||
Stmt *ThenVal,
|
||||
|
|
|
@ -241,10 +241,9 @@ StmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
|
|||
if (SubStmt.isInvalid())
|
||||
SubStmt = Actions.ActOnNullStmt(ColonLoc);
|
||||
|
||||
// FIXME: use attributes?
|
||||
return Actions.ActOnLabelStmt(IdentTok.getLocation(),
|
||||
IdentTok.getIdentifierInfo(),
|
||||
ColonLoc, SubStmt.get());
|
||||
ColonLoc, SubStmt.get(), AttrList.take());
|
||||
}
|
||||
|
||||
/// ParseCaseStatement
|
||||
|
|
|
@ -227,13 +227,35 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
|
|||
|
||||
StmtResult
|
||||
Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
|
||||
SourceLocation ColonLoc, Stmt *SubStmt) {
|
||||
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;
|
||||
llvm::OwningPtr<const AttributeList> AttrList(Attr);
|
||||
for (const AttributeList* a = AttrList.get(); a; a = a->getNext()) {
|
||||
if (a->getKind() == AttributeList::AT_unused) {
|
||||
HasUnusedAttr = true;
|
||||
} else {
|
||||
Diag(a->getLoc(), diag::warn_label_attribute_not_unused);
|
||||
a->setInvalid(true);
|
||||
}
|
||||
}
|
||||
|
||||
return ActOnLabelStmt(IdentLoc, II, ColonLoc, SubStmt, HasUnusedAttr);
|
||||
}
|
||||
|
||||
StmtResult
|
||||
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];
|
||||
|
||||
// If not forward referenced or defined already, just create a new LabelStmt.
|
||||
if (LabelDecl == 0)
|
||||
return Owned(LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt));
|
||||
return Owned(LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt,
|
||||
HasUnusedAttr));
|
||||
|
||||
assert(LabelDecl->getID() == II && "Label mismatch!");
|
||||
|
||||
|
@ -249,6 +271,7 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
|
|||
// definition. Fill in the forward definition and return it.
|
||||
LabelDecl->setIdentLoc(IdentLoc);
|
||||
LabelDecl->setSubStmt(SubStmt);
|
||||
LabelDecl->setUnusedAttribute(HasUnusedAttr);
|
||||
return Owned(LabelDecl);
|
||||
}
|
||||
|
||||
|
|
|
@ -758,8 +758,9 @@ public:
|
|||
StmtResult RebuildLabelStmt(SourceLocation IdentLoc,
|
||||
IdentifierInfo *Id,
|
||||
SourceLocation ColonLoc,
|
||||
Stmt *SubStmt) {
|
||||
return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, SubStmt);
|
||||
Stmt *SubStmt, bool HasUnusedAttr) {
|
||||
return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, SubStmt,
|
||||
HasUnusedAttr);
|
||||
}
|
||||
|
||||
/// \brief Build a new "if" statement.
|
||||
|
@ -3562,7 +3563,7 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
|
|||
// FIXME: Pass the real colon location in.
|
||||
SourceLocation ColonLoc = SemaRef.PP.getLocForEndOfToken(S->getIdentLoc());
|
||||
return getDerived().RebuildLabelStmt(S->getIdentLoc(), S->getID(), ColonLoc,
|
||||
SubStmt.get());
|
||||
SubStmt.get(), S->HasUnusedAttribute());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
|
|
@ -220,6 +220,7 @@ void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
|
|||
S->setSubStmt(Reader.ReadSubStmt());
|
||||
S->setIdentLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
|
||||
S->setUsed(Record[Idx++]);
|
||||
S->setUnusedAttribute(Record[Idx++]);
|
||||
Reader.RecordLabelStmt(S, Record[Idx++]);
|
||||
}
|
||||
|
||||
|
|
|
@ -214,6 +214,7 @@ void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
|
|||
Writer.AddStmt(S->getSubStmt());
|
||||
Writer.AddSourceLocation(S->getIdentLoc(), Record);
|
||||
Record.push_back(S->isUsed());
|
||||
Record.push_back(S->HasUnusedAttribute());
|
||||
Record.push_back(Writer.GetLabelID(S));
|
||||
Code = serialization::STMT_LABEL;
|
||||
}
|
||||
|
|
|
@ -4,5 +4,8 @@ void f() {
|
|||
a:
|
||||
goto a;
|
||||
b: // expected-warning{{unused}}
|
||||
c: __attribute__((unused));
|
||||
d: __attribute__((noreturn)); // expected-warning {{The only valid attribute for labels is 'unused'}}
|
||||
goto d;
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue