]> granicus.if.org Git - clang/commitdiff
Don't warn for an unused label if it has 'unused' attribute. Fixes rdar://8483139.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 28 Sep 2010 14:54:07 +0000 (14:54 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 28 Sep 2010 14:54:07 +0000 (14:54 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114954 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Stmt.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Parse/ParseStmt.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/Sema/warn-unused-label.c

index 0bb257b2e0ebe68e9a3b763cb592920ae3efb997..508bedacd73ff7c9795e272f81957e4e986c99c0 100644 (file)
@@ -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());
   }
index 92a2c1c8594e225c59d7094a692acd4761d19c67..9a2576208fe32f631289e54391e84f9fe1203ce2 100644 (file)
@@ -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">,
index 5d8ead37dc4e0bf3af74613402d71ca4a2dcc03a..dcbf3dc2ca6a18acab5a567f5f79f4bcd3b56256 100644 (file)
@@ -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,
index 5ebee67b7a42f8ebad136487c7ea164e0a1bc8c6..d4523d226ad4fe03f141fe65cd57b145aa11aed6 100644 (file)
@@ -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
index 24489544e0628063eda7db07b45c831b99136a81..7acadc541c727805fdd8b5e57774f712b4c1f9be 100644 (file)
@@ -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);
 }
 
index a865348e4939b10771fdec2510974bd24772c310..71492254c6ef69b60b92de743572d63b431d90bf 100644 (file)
@@ -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>
index 7b0845d5e7b9c241e501b2cbad398771563613a2..ab2bba7283bf05c77795f9b434b40762313257ae 100644 (file)
@@ -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++]);
 }
 
index edd8002d47cbed45831d060d093c84ff200648f8..3905ad68968c81e296e8e5c3d342624facd56d8f 100644 (file)
@@ -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;
 }
index b5979be264f7a578f1da3847896604b501eda458..163446002e6043e5e18727d980bdda973862cc51 100644 (file)
@@ -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;
 }