diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-01-17 18:58:44 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-01-17 18:58:44 +0000 |
commit | ee56962cc1cb0a8f421b4749e52f6a9dcc4d958c (patch) | |
tree | 4ff995c7df053ada59dabd28c358cd9f5d83c260 | |
parent | 834c373e3fdf8d5d0199c6e10e924fdbf94c8366 (diff) | |
download | bcm5719-llvm-ee56962cc1cb0a8f421b4749e52f6a9dcc4d958c.tar.gz bcm5719-llvm-ee56962cc1cb0a8f421b4749e52f6a9dcc4d958c.zip |
Convert "#pragma unused(...)" into tokens for the parser.
This allows us to cache a "#pragma unused" that occurs inside an inline C++ member function.
Fixes rdar://8829590&8770988.
llvm-svn: 123666
-rw-r--r-- | clang/include/clang/Basic/TokenKinds.def | 6 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 3 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 8 | ||||
-rw-r--r-- | clang/lib/Parse/ParsePragma.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 48 | ||||
-rw-r--r-- | clang/test/SemaCXX/pragma-unused.cpp | 8 |
8 files changed, 76 insertions, 35 deletions
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index c61930e67ac..86f6d1ddadf 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -433,6 +433,12 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly ANNOTATION(template_id) // annotation for a C++ template-id that names a // function template specialization (not a type), // e.g., "std::swap<int>" + +// Annotation for #pragma unused(...) +// For each argument inside the parentheses the pragma handler will produce +// one 'pragma_unused' annotation token followed by the argument token. +ANNOTATION(pragma_unused) + #undef ANNOTATION #undef OBJC2_AT_KEYWORD #undef OBJC1_AT_KEYWORD diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 4e7de34d7d6..4ac9eb9987b 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -349,6 +349,9 @@ private: /// based on context. void CodeCompletionRecovery(); + /// \brief Handle the annotation token produced for #pragma unused(...) + void HandlePragmaUnused(); + /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 76b5f523fa7..61c4ec45458 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4299,11 +4299,9 @@ public: SourceLocation RParenLoc); /// ActOnPragmaUnused - Called on well-formed '#pragma unused'. - void ActOnPragmaUnused(const Token *Identifiers, - unsigned NumIdentifiers, Scope *curScope, - SourceLocation PragmaLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc); + void ActOnPragmaUnused(const Token &Identifier, + Scope *curScope, + SourceLocation PragmaLoc); /// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... . void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 42c1c5f5a24..90c7d76cbcc 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -17,6 +17,17 @@ #include "clang/Lex/Preprocessor.h" using namespace clang; +/// \brief Handle the annotation token produced for #pragma unused(...) +/// +/// Each annot_pragma_unused is followed by the argument token so e.g. +/// "#pragma unused(x,y)" becomes: +/// annot_pragma_unused 'x' annot_pragma_unused 'y' +void Parser::HandlePragmaUnused() { + assert(Tok.is(tok::annot_pragma_unused)); + SourceLocation UnusedLoc = ConsumeToken(); + Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc); + ConsumeToken(); // The argument token. +} // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' @@ -301,9 +312,20 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); - // Perform the action to handle the pragma. - Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(), - parser.getCurScope(), UnusedLoc, LParenLoc, RParenLoc); + // For each identifier token, insert into the token stream a + // annot_pragma_unused token followed by the identifier token. + // This allows us to cache a "#pragma unused" that occurs inside an inline + // C++ member function. + + Token *Toks = new Token[2*Identifiers.size()]; + for (unsigned i=0; i != Identifiers.size(); i++) { + Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1]; + pragmaUnusedTok.startToken(); + pragmaUnusedTok.setKind(tok::annot_pragma_unused); + pragmaUnusedTok.setLocation(UnusedLoc); + idTok = Identifiers[i]; + } + PP.EnterTokenStream(Toks, 2*Identifiers.size(), /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); } // #pragma weak identifier diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index b1d40d2a5c1..113b2661b0f 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -465,6 +465,12 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { StmtVector Stmts(Actions); while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + + if (Tok.is(tok::annot_pragma_unused)) { + HandlePragmaUnused(); + continue; + } + StmtResult R; if (Tok.isNot(tok::kw___extension__)) { R = ParseStatementOrDeclaration(Stmts, false); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 473c6ad7b00..47c62377c22 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -404,6 +404,10 @@ void Parser::Initialize() { /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the /// action tells us to. This returns true if the EOF was encountered. bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { + + while (Tok.is(tok::annot_pragma_unused)) + HandlePragmaUnused(); + Result = DeclGroupPtrTy(); if (Tok.is(tok::eof)) { Actions.ActOnEndOfTranslationUnit(); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index de1e1bf6a20..a67c4fbbb22 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -263,37 +263,31 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, } } -void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, - Scope *curScope, - SourceLocation PragmaLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { - - for (unsigned i = 0; i < NumIdentifiers; ++i) { - const Token &Tok = Identifiers[i]; - IdentifierInfo *Name = Tok.getIdentifierInfo(); - LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); - LookupParsedName(Lookup, curScope, NULL, true); - - if (Lookup.empty()) { - Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) - << Name << SourceRange(Tok.getLocation()); - continue; - } +void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, + SourceLocation PragmaLoc) { - VarDecl *VD = Lookup.getAsSingle<VarDecl>(); - if (!VD || !(VD->hasLocalStorage() || VD->isStaticLocal())) { - Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) - << Name << SourceRange(Tok.getLocation()); - continue; - } + IdentifierInfo *Name = IdTok.getIdentifierInfo(); + LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName); + LookupParsedName(Lookup, curScope, NULL, true); - // Warn if this was used before being marked unused. - if (VD->isUsed()) - Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name; + if (Lookup.empty()) { + Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) + << Name << SourceRange(IdTok.getLocation()); + return; + } - VD->addAttr(::new (Context) UnusedAttr(Tok.getLocation(), Context)); + VarDecl *VD = Lookup.getAsSingle<VarDecl>(); + if (!VD || !(VD->hasLocalStorage() || VD->isStaticLocal())) { + Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) + << Name << SourceRange(IdTok.getLocation()); + return; } + + // Warn if this was used before being marked unused. + if (VD->isUsed()) + Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name; + + VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context)); } typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack; diff --git a/clang/test/SemaCXX/pragma-unused.cpp b/clang/test/SemaCXX/pragma-unused.cpp new file mode 100644 index 00000000000..c9ddffafafa --- /dev/null +++ b/clang/test/SemaCXX/pragma-unused.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-parameter -Wunused -verify %s + +struct S { + void m(int x, int y) { + int z; + #pragma unused(x,y,z) + } +}; |