[cfe-dev] handle __attribute__((deprecated))

Ted Kremenek kremenek at apple.com
Mon Mar 3 09:47:55 PST 2008

On Mar 1, 2008, at 12:28 AM, Chris Lattner wrote:

> Should this emit a diagnostic if it's not a function?  Ted, can you  
> please review the rest of the 'HandleFormatAttribute' method?

Hi Nuno,

I've reviewed the version of HandleFormatAttribute that Chris  
committed to the clang tree from your latest patch.  Thanks again for  
submitting this patch.  It's a great contribution.  I have a few  

   // FIXME: in C++ the implicit 'this' function parameter also counts.
   // the index must start in 1 and the limit is numargs+1
   unsigned NumArgs = Fn->getNumParams()+1; // +1 for ...

This looks incorrect for all code except non-static C++ methods, of  
which we do not currently handle.  The code after this frequently  
checks against NumArgs, which will be incorrect (off-by-one).  Also,  
I'm not certain how we are actually going to handle declarations for  
class members, but chances are we are not going to use FunctionDecls.   
I would just remove the increment for now, and leave the FIXME.  When  
I first looked at this code I was also a little confused; I thought  
you were trying to offset for a deficiency in the AST, rather than the  
fact that this is a game that the format attribute plays in GCC (i.e.,  
offsetting for the implicit "this" pointer):

   "Since non-static C++ methods have an implicit this argument, the  
arguments of such methods should be counted from two, not one..."

Make a comment that this is is mirroring GCC behavior when it comes to  
C++ non-static methods and the format attribute.  It also seems that  
offsets to the base index would have to be handled as well.  I would  
just punt on this for now until we have Decls for C++ methods in  
place.  I'm a little concerned about doing this right for C++ non- 
static methods; having little fudges like these to indices and ranges  
is a great source for off-by-one and buffer overflow errors if not all  
of the code obeys the rule.  This behavior just seems like a GCC  
kludge, with the ASTs being tied to closely to the implementation of  
how methods are code generated (thus forcing the attribute  
specification itself to be broken); in reality, the "this" pointer  
would never be used as a format string, so we probably should just  
pretend that it isn't there when processing the format argument  
indices.  This means that in the code below your original increment of  
NumArgs that we should instead *decrement* the parsed indices when  
handling C++ non-static methods.  That way, the FormatAttr object  
always stores the canonicalized indices for the *explicit* function  
arguments (again, ignoring the "this" argument).

More comments:

   Expr *IdxExpr = static_cast<Expr *>(rawAttr->getArg(0));
   llvm::APSInt Idx(32);
   if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) {
     Diag(rawAttr->getLoc(), diag::err_attribute_argument_n_not_int,
            "format", std::string("2"), IdxExpr->getSourceRange());

Please do not hardcode "32" or the signedness of Idx, both which could  
be target specific.  Please query these using  
Context::getTypeSize(IdxExpr) and IdxExpr->getType()- 

For the following block, please add a big comment indicating what it  
is trying to do:

   Expr *IdxExpr = static_cast<Expr *>(rawAttr->getArg(0));
   llvm::APSInt Idx(32);
   if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) {
     Diag(rawAttr->getLoc(), diag::err_attribute_argument_n_not_int,
            "format", std::string("2"), IdxExpr->getSourceRange());

   if (Idx.getZExtValue() < 1 || Idx.getZExtValue() > NumArgs) {
     Diag(rawAttr->getLoc(), diag::err_attribute_argument_out_of_bounds,
            "format", std::string("2"), IdxExpr->getSourceRange());

   Expr *FirstArgExpr = static_cast<Expr *>(rawAttr->getArg(1));
   llvm::APSInt FirstArg(32);
   if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, Context)) {
     Diag(rawAttr->getLoc(), diag::err_attribute_argument_n_not_int,
            "format", std::string("3"), FirstArgExpr->getSourceRange());

   if (FormatLen == 8 && !memcmp(Format, "strftime", 8)) {
     if (FirstArg.getZExtValue() != 0) {
   } else if (FirstArg.getZExtValue() > NumArgs) {
     Diag(rawAttr->getLoc(), diag::err_attribute_argument_out_of_bounds,
            "format", std::string("3"), FirstArgExpr->getSourceRange());

As far as comments are concerned, it would be great to see a citation  
link to the appropriate references.  For example, the following link  
provides GCC's documentation on format argument attributes:


Adding this link in a comment would be helpful so that people know  
what this code is trying to implement.  This mirrors documentation  
through the rest of clang where we try to cite either the C standard  
or the appropriate reference.    Also, please add comments above  
checks like "if (FirstArg.getZExtValue() != 0)" where the argument is  
not suppose to be zero and *why*.

There is no harm in adding comments that document behavior; for  
example, before seeing this code I did not know that the format  
attribute supported the __strftime__ and __strfmon__ archetypes.  I  
don't think GCC always supported these archetypes, so adding some  
comments saying what functionality this adds to the format attribute  
would be incredibly useful to other people browsing this code (which  
is one of the goals of clang).

Overall, this patch looks very good, and like your previous patches,  
it's a great contribution to clang.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20080303/4159856b/attachment.html>

More information about the cfe-dev mailing list