summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-01-17 18:58:44 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-01-17 18:58:44 +0000
commitee56962cc1cb0a8f421b4749e52f6a9dcc4d958c (patch)
tree4ff995c7df053ada59dabd28c358cd9f5d83c260
parent834c373e3fdf8d5d0199c6e10e924fdbf94c8366 (diff)
downloadbcm5719-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.def6
-rw-r--r--clang/include/clang/Parse/Parser.h3
-rw-r--r--clang/include/clang/Sema/Sema.h8
-rw-r--r--clang/lib/Parse/ParsePragma.cpp28
-rw-r--r--clang/lib/Parse/ParseStmt.cpp6
-rw-r--r--clang/lib/Parse/Parser.cpp4
-rw-r--r--clang/lib/Sema/SemaAttr.cpp48
-rw-r--r--clang/test/SemaCXX/pragma-unused.cpp8
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)
+ }
+};
OpenPOWER on IntegriCloud