forked from OSchip/llvm-project
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:
parent
0e9fb28e95
commit
88336839b9
|
@ -6471,6 +6471,9 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
|||
/// These attributes can apply both to implicitly-declared builtins
|
||||
/// (like __builtin___printf_chk) or to library-declared functions
|
||||
/// 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) {
|
||||
if (FD->isInvalidDecl())
|
||||
return;
|
||||
|
@ -6504,9 +6507,9 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
|
|||
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));
|
||||
if (Context.BuiltinInfo.isConst(BuiltinID))
|
||||
if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->getAttr<ConstAttr>())
|
||||
FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
|
||||
}
|
||||
|
||||
|
|
|
@ -1526,8 +1526,13 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
// check the attribute arguments.
|
||||
|
@ -1536,8 +1541,13 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
// check the attribute arguments.
|
||||
|
@ -1904,6 +1914,23 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
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,
|
||||
Idx.getZExtValue(),
|
||||
FirstArg.getZExtValue()));
|
||||
|
|
|
@ -358,3 +358,8 @@ void pr9314() {
|
|||
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'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue