diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-08-03 23:24:57 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-08-03 23:24:57 +0000 |
commit | fb50bf5a6f16fe2376f2b4276d40ec10ea0d538b (patch) | |
tree | 324e5ffaeac9d80b1b1eac8f5abeae5faa8c062a /clang/lib/Sema/SemaAttr.cpp | |
parent | d673098480b7572fae5119f253755ccde5ad193d (diff) | |
download | bcm5719-llvm-fb50bf5a6f16fe2376f2b4276d40ec10ea0d538b.tar.gz bcm5719-llvm-fb50bf5a6f16fe2376f2b4276d40ec10ea0d538b.zip |
Per advice that Doug Gregor gave me several months ago, clean up the
implementation of '#pragma unused' by not constructing intermediate
DeclRefExprs, but instead do the name lookup directly. The
implementation is greatly simplified.
Along the way, degrade '#pragma unused(undeclaredvariable)' to a
warning instead of being a hard error. This implements:
<rdar://problem/6761874> [sema] allow #pragma unused to reference undefined variable (with warning)
llvm-svn: 78019
Diffstat (limited to 'clang/lib/Sema/SemaAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 55 |
1 files changed, 24 insertions, 31 deletions
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 1bf8444c42b..6622d53659e 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -170,42 +170,35 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, } } -void Sema::ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs, +void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, + Scope *curScope, 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; + for (unsigned i = 0; i < NumIdentifiers; ++i) { + const Token &Tok = Identifiers[i]; + IdentifierInfo *Name = Tok.getIdentifierInfo(); + const LookupResult &Lookup = LookupParsedName(curScope, NULL, Name, + LookupOrdinaryName, + false, true, + Tok.getLocation()); + // FIXME: Handle Lookup.isAmbiguous? + + NamedDecl *ND = Lookup.getAsDecl(); + + if (!ND) { + Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) + << Name << SourceRange(Tok.getLocation()); + continue; } - } - - // 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()); - DR->Destroy(Context); + if (!isa<VarDecl>(ND) || !cast<VarDecl>(ND)->hasLocalStorage()) { + Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) + << Name << SourceRange(Tok.getLocation()); + continue; + } + + ND->addAttr(::new (Context) UnusedAttr()); } } |