aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-06-15 05:45:11 +0000
committerDouglas Gregor <dgregor@apple.com>2011-06-15 05:45:11 +0000
commitb30cd4a09bbf0adfa644b957a2b28fe31c5d45e4 (patch)
tree2575b4040d2b99238b79026ea5598fd034e876cf
parent210c05b10317a11971f87e474ffa4c30bb8e4df9 (diff)
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>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133045 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp7
-rw-r--r--lib/Sema/SemaDeclAttr.cpp33
-rw-r--r--test/Sema/format-strings.c5
3 files changed, 40 insertions, 5 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 49e59c76aa..c7545cf532 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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));
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 7f93ab72d6..1ec7199562 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -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;
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) {
@@ -1536,7 +1541,12 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
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) {
@@ -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()));
diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c
index c78095a04d..35210c341a 100644
--- a/test/Sema/format-strings.c
+++ b/test/Sema/format-strings.c
@@ -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'}}
+}