Don't add redundant FormatAttr, ConstAttr, or NoThrowAttr attributes,

either imlicitly (for builtins) or explicitly (due to multiple
specification of the same attributes). Fixes <rdar://problem/9612060>.

llvm-svn: 133045
This commit is contained in:
Douglas Gregor 2011-06-15 05:45:11 +00:00
parent 0e9fb28e95
commit 88336839b9
3 changed files with 40 additions and 5 deletions

View File

@ -6471,6 +6471,9 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/// These attributes can apply both to implicitly-declared builtins /// These attributes can apply both to implicitly-declared builtins
/// (like __builtin___printf_chk) or to library-declared functions /// (like __builtin___printf_chk) or to library-declared functions
/// like NSLog or printf. /// like NSLog or printf.
///
/// We need to check for duplicate attributes both here and where user-written
/// attributes are applied to declarations.
void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
if (FD->isInvalidDecl()) if (FD->isInvalidDecl())
return; return;
@ -6504,9 +6507,9 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
} }
if (Context.BuiltinInfo.isNoThrow(BuiltinID)) if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->getAttr<NoThrowAttr>())
FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context)); FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
if (Context.BuiltinInfo.isConst(BuiltinID)) if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->getAttr<ConstAttr>())
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
} }

View File

@ -1525,8 +1525,13 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
return; return;
} }
d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context)); if (NoThrowAttr *Existing = d->getAttr<NoThrowAttr>()) {
if (Existing->getLocation().isInvalid())
Existing->setLocation(Attr.getLoc());
} else {
d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context));
}
} }
static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1536,7 +1541,12 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context)); if (ConstAttr *Existing = d->getAttr<ConstAttr>()) {
if (Existing->getLocation().isInvalid())
Existing->setLocation(Attr.getLoc());
} else {
d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context));
}
} }
static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@ -1904,6 +1914,23 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return; return;
} }
// Check whether we already have an equivalent format attribute.
for (specific_attr_iterator<FormatAttr>
i = d->specific_attr_begin<FormatAttr>(),
e = d->specific_attr_end<FormatAttr>();
i != e ; ++i) {
FormatAttr *f = *i;
if (f->getType() == Format &&
f->getFormatIdx() == (int)Idx.getZExtValue() &&
f->getFirstArg() == (int)FirstArg.getZExtValue()) {
// If we don't have a valid location for this attribute, adopt the
// location.
if (f->getLocation().isInvalid())
f->setLocation(Attr.getLoc());
return;
}
}
d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format, d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format,
Idx.getZExtValue(), Idx.getZExtValue(),
FirstArg.getZExtValue())); FirstArg.getZExtValue()));

View File

@ -358,3 +358,8 @@ void pr9314() {
printf(__func__); // no-warning printf(__func__); // no-warning
} }
int printf(const char * restrict, ...) __attribute__((__format__ (__printf__, 1, 2)));
void rdar9612060(void) {
printf("%s", 2); // expected-warning{{conversion specifies type 'char *' but the argument has type 'int'}}
}