]> granicus.if.org Git - clang/commitdiff
Implement -Wunused-label.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 19 Sep 2010 21:21:25 +0000 (21:21 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 19 Sep 2010 21:21:25 +0000 (21:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114315 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Stmt.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaStmt.cpp
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/Sema/warn-unused-label.c [new file with mode: 0644]
test/Sema/warn-unused-value.c

index 856a14c51a1d166203cb9d2aa1ba59ae438dccd8..0bb257b2e0ebe68e9a3b763cb592920ae3efb997 100644 (file)
@@ -561,10 +561,11 @@ class LabelStmt : public Stmt {
   IdentifierInfo *Label;
   Stmt *SubStmt;
   SourceLocation IdentLoc;
+  bool Used : 1;
 public:
   LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
     : Stmt(LabelStmtClass), Label(label),
-      SubStmt(substmt), IdentLoc(IL) {}
+      SubStmt(substmt), IdentLoc(IL), Used(false) {}
 
   // \brief Build an empty label statement.
   explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
@@ -578,6 +579,11 @@ public:
   void setIdentLoc(SourceLocation L) { IdentLoc = L; }
   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; }
+  void setUsed(bool U = true) { Used = U; }
+
   virtual SourceRange getSourceRange() const {
     return SourceRange(IdentLoc, SubStmt->getLocEnd());
   }
index b0dcf320d545ce9b0a21fe0fd17b47aa7c1dc0fc..9508c913ec341e0998e05134fecf901ad8e0dacf 100644 (file)
@@ -1899,6 +1899,8 @@ def warn_missing_braces : Warning<
 
 def err_redefinition_of_label : Error<"redefinition of label '%0'">;
 def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
+def warn_unused_label : Warning<"unused label '%0'">,
+  InGroup<UnusedLabel>, DefaultIgnore;
 
 def err_goto_into_protected_scope : Error<"goto into protected scope">;
 def err_switch_into_protected_scope : Error<
index 51b5ae91d6aed75ad5f3aa2cff1cb2203dbc683b..0b3e60f82a80e07f5fc4716e4845846e93af84cf 100644 (file)
@@ -5028,8 +5028,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
     // 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->getSubStmt() != 0)
+    if (L->getSubStmt() != 0) {
+      if (!L->isUsed())
+        Diag(L->getIdentLoc(), diag::warn_unused_label) << L->getName();
       continue;
+    }
 
     // Emit error.
     Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
index 4bd596b6728508eeb1193253841862be0812fa66..4000984448267bd9c1e59f957d3f0e437c1be368 100644 (file)
@@ -6871,6 +6871,7 @@ ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
   if (LabelDecl == 0)
     LabelDecl = new (Context) LabelStmt(LabLoc, LabelII, 0);
 
+  LabelDecl->setUsed();
   // Create the AST node.  The address of a label always has type 'void*'.
   return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, LabelDecl,
                                        Context.getPointerType(Context.VoidTy)));
@@ -7355,8 +7356,11 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
 
     // 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.
-    if (L->getSubStmt() != 0)
+    if (L->getSubStmt() != 0) {
+      if (!L->isUsed())
+        Diag(L->getIdentLoc(), diag::warn_unused_label) << L->getName();
       continue;
+    }
 
     // Emit error.
     Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
index 47ea4f2c2535e124a81221f02fec277fb0926d0e..24489544e0628063eda7db07b45c831b99136a81 100644 (file)
@@ -994,6 +994,7 @@ Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
   if (LabelDecl == 0)
     LabelDecl = new (Context) LabelStmt(LabelLoc, LabelII, 0);
 
+  LabelDecl->setUsed();
   return Owned(new (Context) GotoStmt(LabelDecl, GotoLoc, LabelLoc));
 }
 
index 6e8ad4fc447ec53229daf0bbd70a703893e81525..7b0845d5e7b9c241e501b2cbad398771563613a2 100644 (file)
@@ -219,6 +219,7 @@ void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
   S->setID(Reader.GetIdentifierInfo(Record, Idx));
   S->setSubStmt(Reader.ReadSubStmt());
   S->setIdentLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setUsed(Record[Idx++]);
   Reader.RecordLabelStmt(S, Record[Idx++]);
 }
 
index 7a5b9497a82852c1e2e9d1e8ed124e00f31dc6a7..edd8002d47cbed45831d060d093c84ff200648f8 100644 (file)
@@ -213,6 +213,7 @@ void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
   Writer.AddIdentifierRef(S->getID(), Record);
   Writer.AddStmt(S->getSubStmt());
   Writer.AddSourceLocation(S->getIdentLoc(), Record);
+  Record.push_back(S->isUsed());
   Record.push_back(Writer.GetLabelID(S));
   Code = serialization::STMT_LABEL;
 }
diff --git a/test/Sema/warn-unused-label.c b/test/Sema/warn-unused-label.c
new file mode 100644 (file)
index 0000000..b5979be
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused-label -verify %s
+
+void f() {
+  a:
+  goto a;
+  b: // expected-warning{{unused}}
+  return;
+}
index 7c36b6983e701dba2d989d4c97f6dfc9587ee9c4..876eb9e4823e563e4855b6c38e99b43ba8e7a104 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -Wunused-label %s
 // RUN: %clang_cc1 -fsyntax-only -verify -Wunused %s
 // RUN: %clang_cc1 -fsyntax-only -verify -Wall %s
 
@@ -53,7 +53,7 @@ void pr4806() {
   *pi;              // expected-warning {{expression result unused}}
   *pj;
 
-  foo_label:
+  foo_label:        // expected-warning {{unused label}}
   i;                // expected-warning {{expression result unused}}
 }