[cfe-commits] r67569 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParsePragma.cpp lib/Parse/ParsePragma.h lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaAttr.cpp test/Sema/pragma-unused.c

Douglas Gregor dgregor at apple.com
Mon Mar 23 15:42:58 PDT 2009


On Mar 23, 2009, at 3:28 PM, Ted Kremenek wrote:

> Author: kremenek
> Date: Mon Mar 23 17:28:25 2009
> New Revision: 67569
>
> URL: http://llvm.org/viewvc/llvm-project?rev=67569&view=rev
> Log:
> Implement '#pragma unused'.

Cool. Some comments below.

> Modified: cfe/trunk/include/clang/Parse/Action.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=67569&r1=67568&r2=67569&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- cfe/trunk/include/clang/Parse/Action.h (original)
> +++ cfe/trunk/include/clang/Parse/Action.h Mon Mar 23 17:28:25 2009
> @@ -1483,6 +1483,14 @@
>                                SourceLocation RParenLoc) {
>     return;
>   }
> +
> +  /// ActOnPragmaPack - Called on well formed #pragma pack(...).
> +  virtual void ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs,
> +                                 SourceLocation PragmaLoc,
> +                                 SourceLocation LParenLoc,
> +                                 SourceLocation RParenLoc) {
> +    return;
> +  }

The comment here refers to #pragma pack, not #pragma unused.


> +// #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);
> +}

We're going through some extra work here. For each name, we call  
ActOnIdentifierExpr to build a DeclRefExpr, then we have to reverse- 
engineer the DeclRefExpr in ActOnPragmaUnused. Perhaps it would be  
easier to pass arrays of identifiers and locations into  
ActOnPragmaUnused, and skip the interim representation as a  
DeclRefExpr? ActOnPragmaUnused will, of course, need to receive the  
scope so that it can perform lookup for those identifiers.


> Modified: cfe/trunk/lib/Sema/SemaAttr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAttr.cpp?rev=67569&r1=67568&r2=67569&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/lib/Sema/SemaAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaAttr.cpp Mon Mar 23 17:28:25 2009
> @@ -170,3 +170,41 @@
>   }
> }
>
> +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());
> +  }
> +}

Much of this code could be simplified if we just performed the lookup  
of these variables here. Also, aren't we leaking the DeclRefExprs in  
the case where the #pragma unused is well-formed?

	- Doug



More information about the cfe-commits mailing list