forked from OSchip/llvm-project
parent
c8e54db801
commit
fd14fade2f
|
@ -234,16 +234,24 @@ def warn_cxx0x_right_shift_in_template_arg : Warning<
|
|||
|
||||
|
||||
// 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
|
||||
|
|
|
@ -117,6 +117,8 @@ def warn_pragma_pack_pop_identifer_and_alignment : Warning<
|
|||
"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<
|
||||
|
|
|
@ -1483,6 +1483,14 @@ public:
|
|||
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
|
||||
|
|
|
@ -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 @@ namespace clang {
|
|||
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 @@ public:
|
|||
/// been read.
|
||||
///
|
||||
class Parser {
|
||||
friend class PragmaUnusedHandler;
|
||||
PrettyStackTraceParserEntry CrashInfo;
|
||||
|
||||
Preprocessor &PP;
|
||||
|
@ -75,7 +78,8 @@ class Parser {
|
|||
/// 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++
|
||||
|
|
|
@ -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 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
|||
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 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
|||
}
|
||||
|
||||
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 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
namespace clang {
|
||||
class Action;
|
||||
class Parser;
|
||||
|
||||
class PragmaPackHandler : public PragmaHandler {
|
||||
Action &Actions;
|
||||
|
@ -27,6 +28,16 @@ public:
|
|||
|
||||
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
|
||||
|
||||
|
|
|
@ -31,9 +31,14 @@ Parser::Parser(Preprocessor &pp, Action &actions)
|
|||
|
||||
// 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 @@ Parser::~Parser() {
|
|||
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.
|
||||
|
|
|
@ -2073,6 +2073,12 @@ public:
|
|||
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;
|
||||
|
|
|
@ -170,3 +170,41 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
|
|||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue