[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