[cfe-commits] r67569 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParsePragma.cpp lib/Parse/ParsePragma.h lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaAttr.cpp test/Sema/pragma-unused.c

Ted Kremenek kremenek at apple.com
Mon Mar 23 15:28:25 PDT 2009


Author: kremenek
Date: Mon Mar 23 17:28:25 2009
New Revision: 67569

URL: http://llvm.org/viewvc/llvm-project?rev=67569&view=rev
Log:
Implement '#pragma unused'.

Added:
    cfe/trunk/test/Sema/pragma-unused.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParsePragma.cpp
    cfe/trunk/lib/Parse/ParsePragma.h
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaAttr.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Mar 23 17:28:25 2009
@@ -234,16 +234,24 @@
 
 
 // Language specific pragmas
-// #pragma pack
-def warn_pragma_pack_expected_lparen : Warning<
-  "missing '(' after '#pragma pack' - ignoring">;
-def warn_pragma_pack_expected_rparen : Warning<
-  "missing ')' after '#pragma pack' - ignoring">;
+// - Generic warnings
+def warn_pragma_expected_lparen : Warning<
+  "missing '(' after '#pragma %0' - ignoring">;
+def warn_pragma_expected_rparen : Warning<
+  "missing ')' after '#pragma %0' - ignoring">;
+def warn_pragma_expected_identifier : Warning<
+  "expected identifier in '#pragma %0' - ignored">;  
+// - #pragma pack
 def warn_pragma_pack_invalid_action : Warning<
   "unknown action for '#pragma pack' - ignored">;
 def warn_pragma_pack_invalid_constant : Warning<
   "invalid constant for '#pragma pack', expected %0 - ignored">;
 def warn_pragma_pack_malformed : Warning<
   "expected integer or identifier in '#pragma pack' - ignored">;
-
-}
+// - #pragma unused
+def warn_pragma_unused_expected_var : Warning<
+  "expected '#pragma unused' argument to be a variable name">;
+def warn_pragma_unused_expected_punc : Warning<
+  "expected ')' or ',' in '#pragma unused'">;
+  
+} // end of Parser diagnostics

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Mar 23 17:28:25 2009
@@ -117,6 +117,8 @@
   "specifying both a name and alignment to 'pop' is undefined">;
 def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
 
+def warn_pragma_unused_expected_localvar : Warning<
+  "only local variables can be arguments to '#pragma unused'">;
 
 /// Objective-C parser diagnostics
 def err_duplicate_class_def : Error<

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Mar 23 17:28:25 2009
@@ -1483,6 +1483,14 @@
                                SourceLocation RParenLoc) {
     return;
   }
+  
+  /// ActOnPragmaPack - Called on well formed #pragma pack(...).
+  virtual void ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs,
+                                 SourceLocation PragmaLoc, 
+                                 SourceLocation LParenLoc,
+                                 SourceLocation RParenLoc) {
+    return;
+  }  
 };
 
 /// MinimalAction - Minimal actions are used by light-weight clients of the

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Mar 23 17:28:25 2009
@@ -17,6 +17,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Parse/Action.h"
 #include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/OwningPtr.h"
 #include <stack>
 #include <list>
 
@@ -26,6 +27,7 @@
   class Scope;
   class DiagnosticBuilder;
   class Parser;
+  class PragmaUnusedHandler;
 
 /// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
 /// an entry is printed for it.
@@ -42,6 +44,7 @@
 /// been read.
 ///
 class Parser {
+  friend class PragmaUnusedHandler;
   PrettyStackTraceParserEntry CrashInfo;
   
   Preprocessor &PP;
@@ -75,7 +78,8 @@
   /// comparison.
   IdentifierInfo *Ident_super;
 
-  PragmaHandler *PackHandler;
+  llvm::OwningPtr<PragmaHandler> PackHandler;
+  llvm::OwningPtr<PragmaHandler> UnusedHandler;
 
   /// Whether the '>' token acts as an operator or not. This will be
   /// true except when we are parsing an expression within a C++

Modified: cfe/trunk/lib/Parse/ParsePragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParsePragma.cpp (original)
+++ cfe/trunk/lib/Parse/ParsePragma.cpp Mon Mar 23 17:28:25 2009
@@ -15,6 +15,7 @@
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Parse/Action.h"
+#include "clang/Parse/Parser.h"
 using namespace clang;
 
 // #pragma pack(...) comes in the following delicious flavors:
@@ -28,7 +29,7 @@
   Token Tok;
   PP.Lex(Tok);
   if (Tok.isNot(tok::l_paren)) {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_expected_lparen);
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
     return;
   }
 
@@ -95,7 +96,7 @@
   }
 
   if (Tok.isNot(tok::r_paren)) {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_expected_rparen);
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
     return;
   }
 
@@ -104,3 +105,78 @@
                           LParenLoc, RParenLoc);
 }
 
+// #pragma unused(identifier)
+void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
+  // FIXME: Should we be expanding macros here? My guess is no.
+  SourceLocation UnusedLoc = UnusedTok.getLocation();
+  
+  // Lex the left '('.
+  Token Tok;
+  PP.Lex(Tok);
+  if (Tok.isNot(tok::l_paren)) {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
+    return;
+  }
+  SourceLocation LParenLoc = Tok.getLocation();
+  
+  // Lex the declaration reference(s).
+  llvm::SmallVector<Action::ExprTy*, 5> Ex;
+  SourceLocation RParenLoc;
+  bool LexID = true;
+  
+  while (true) {
+    PP.Lex(Tok);
+    
+    if (LexID) {
+      if (Tok.is(tok::identifier)) {            
+        Action::OwningExprResult Name = 
+          Actions.ActOnIdentifierExpr(parser.CurScope, Tok.getLocation(),
+                                      *Tok.getIdentifierInfo(), false);
+      
+        if (Name.isInvalid()) {
+          if (!Ex.empty())
+            Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
+          return;
+        }
+        
+        Ex.push_back(Name.release());        
+        LexID = false;
+        continue;
+      }
+
+      // Illegal token! Release the parsed expressions (if any) and emit
+      // a warning.
+      if (!Ex.empty())
+        Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
+      
+      PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
+      return;
+    }
+    
+    // We are execting a ')' or a ','.
+    if (Tok.is(tok::comma)) {
+      LexID = true;
+      continue;
+    }
+    
+    if (Tok.is(tok::r_paren)) {
+      RParenLoc = Tok.getLocation();
+      break;
+    }
+    
+    // Illegal token! Release the parsed expressions (if any) and emit
+    // a warning.
+    if (!Ex.empty())
+      Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
+    
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
+    return;
+  }
+  
+  // Verify that we have a location for the right parenthesis.
+  assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
+  assert(!Ex.empty() && "Valid '#pragma unused' must have arguments");
+
+  // Perform the action to handle the pragma.    
+  Actions.ActOnPragmaUnused(&Ex[0], Ex.size(), UnusedLoc, LParenLoc, RParenLoc);
+}

Modified: cfe/trunk/lib/Parse/ParsePragma.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.h?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParsePragma.h (original)
+++ cfe/trunk/lib/Parse/ParsePragma.h Mon Mar 23 17:28:25 2009
@@ -18,6 +18,7 @@
 
 namespace clang {
   class Action;
+  class Parser;
 
 class PragmaPackHandler : public PragmaHandler {
   Action &Actions;
@@ -27,6 +28,16 @@
   
   virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);  
 };
+  
+class PragmaUnusedHandler : public PragmaHandler {
+  Action &Actions;
+  Parser &parser;
+public:
+  PragmaUnusedHandler(const IdentifierInfo *N, Action &A, Parser& p)
+    : PragmaHandler(N), Actions(A), parser(p) {}
+  
+  virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);  
+};  
 
 }  // end namespace clang
 

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Mar 23 17:28:25 2009
@@ -31,9 +31,14 @@
 
   // Add #pragma handlers. These are removed and destroyed in the
   // destructor.
-  PackHandler =
-    new PragmaPackHandler(&PP.getIdentifierTable().get("pack"), actions);
-  PP.AddPragmaHandler(0, PackHandler);
+  PackHandler.reset(new
+          PragmaPackHandler(&PP.getIdentifierTable().get("pack"), actions));
+  PP.AddPragmaHandler(0, PackHandler.get());
+      
+  UnusedHandler.reset(new
+          PragmaUnusedHandler(&PP.getIdentifierTable().get("unused"), actions,
+                              *this));
+  PP.AddPragmaHandler(0, UnusedHandler.get());
 
   // Instantiate a LexedMethodsForTopClass for all the non-nested classes.
   PushTopClassStack();
@@ -282,8 +287,10 @@
     delete ScopeCache[i];
 
   // Remove the pragma handlers we installed.
-  PP.RemovePragmaHandler(0, PackHandler);
-  delete PackHandler;
+  PP.RemovePragmaHandler(0, PackHandler.get());
+  PackHandler.reset();
+  PP.RemovePragmaHandler(0, UnusedHandler.get());
+  UnusedHandler.reset();
 }
 
 /// Initialize - Warm up the parser.

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Mar 23 17:28:25 2009
@@ -2073,6 +2073,12 @@
                                SourceLocation LParenLoc,
                                SourceLocation RParenLoc);
   
+  /// ActOnPragmaUnused - Called on well-formed '#pragma unused'.
+  virtual void ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs,
+                                 SourceLocation PragmaLoc, 
+                                 SourceLocation LParenLoc,
+                                 SourceLocation RParenLoc);
+  
   /// getPragmaPackAlignment() - Return the current alignment as specified by
   /// the current #pragma pack directive, or 0 if none is currently active.
   unsigned getPragmaPackAlignment() const;

Modified: cfe/trunk/lib/Sema/SemaAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAttr.cpp?rev=67569&r1=67568&r2=67569&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAttr.cpp Mon Mar 23 17:28:25 2009
@@ -170,3 +170,41 @@
   }
 }
 
+void Sema::ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs,
+                             SourceLocation PragmaLoc,
+                             SourceLocation LParenLoc,
+                             SourceLocation RParenLoc) {
+  
+  // Verify that all of the expressions are valid before
+  // modifying the attributes of any referenced decl.
+  Expr *ErrorExpr = 0;
+  
+  for (unsigned i = 0; i < NumExprs; ++i) {  
+    Expr *Ex = (Expr*) Exprs[i];
+    if (!isa<DeclRefExpr>(Ex)) {
+      ErrorExpr = Ex;
+      break;
+    }
+
+    Decl *d = cast<DeclRefExpr>(Ex)->getDecl();;
+
+    if (!isa<VarDecl>(d) || !cast<VarDecl>(d)->hasLocalStorage()) {
+      ErrorExpr = Ex;
+      break;
+    }
+  }
+  
+  // Delete the expressions if we encountered any error.
+  if (ErrorExpr) {
+    Diag(ErrorExpr->getLocStart(), diag::warn_pragma_unused_expected_localvar);
+    for (unsigned i = 0; i < NumExprs; ++i)
+      ((Expr*) Exprs[i])->Destroy(Context);    
+    return;
+  }
+      
+  // Otherwise, add the 'unused' attribute to each referenced declaration.
+  for (unsigned i = 0; i < NumExprs; ++i) {
+    DeclRefExpr *DR = (DeclRefExpr*) Exprs[i];
+    DR->getDecl()->addAttr(::new (Context) UnusedAttr());
+  }
+}

Added: cfe/trunk/test/Sema/pragma-unused.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/pragma-unused.c?rev=67569&view=auto

==============================================================================
--- cfe/trunk/test/Sema/pragma-unused.c (added)
+++ cfe/trunk/test/Sema/pragma-unused.c Mon Mar 23 17:28:25 2009
@@ -0,0 +1,38 @@
+// RUN: clang -fsyntax-only -verify %s
+
+void f1(void) {
+  int x, y, z;
+  #pragma unused(x)
+  #pragma unused(y, z)
+  
+  int w; // FIXME: We should emit a warning that 'w' is unused.  
+  #pragma unused w // expected-warning{{missing '(' after '#pragma unused' - ignoring}}
+}
+
+void f2(void) {
+  int x, y;
+  #pragma unused(x,) // expected-warning{{expected '#pragma unused' argument to be a variable name}}
+  #pragma unused() // expected-warning{{expected '#pragma unused' argument to be a variable name}}
+}
+
+void f3(void) {
+  #pragma unused(x) // expected-error{{use of undeclared identifier 'x'}}
+}
+
+void f4(void) {
+  int w; // FIXME: We should emit a warning that 'w' is unused.
+  #pragma unused((w)) // expected-warning{{expected '#pragma unused' argument to be a variable name}}
+}
+
+int k;
+void f5(void) {
+  #pragma unused(k) // expected-warning{{only local variables can be arguments to '#pragma unused' - ignored}}
+}
+
+void f6(void) {
+  int z; // no-warning
+  {
+    #pragma unused(z) // no-warning
+  }
+}
+





More information about the cfe-commits mailing list