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
|
/// 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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'}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue