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)



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78019 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 1bf8444..6622d53 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -170,42 +170,35 @@
   }
 }
 
-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();;
+  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?
 
-    if (!isa<VarDecl>(d) || !cast<VarDecl>(d)->hasLocalStorage()) {
-      ErrorExpr = Ex;
-      break;
+    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());
   }
 }