]> granicus.if.org Git - clang/commitdiff
Don't add redundant FormatAttr, ConstAttr, or NoThrowAttr attributes,
authorDouglas Gregor <dgregor@apple.com>
Wed, 15 Jun 2011 05:45:11 +0000 (05:45 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 15 Jun 2011 05:45:11 +0000 (05:45 +0000)
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

lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/Sema/format-strings.c

index 49e59c76aa8961e5d00079b9cfd7f99ba896d7b2..c7545cf532426862c87842824789c4d27452168d 100644 (file)
@@ -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));
   }
 
index 7f93ab72d6d1c0903da82fa4e1289a8c4a964bd4..1ec7199562422356e72b74eba2f25dd65bc6be93 100644 (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;
     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()));
index c78095a04d7b540dda8b8209a2a0bc1c41756547..35210c341a524fb3295daa9e21e944331878f6f2 100644 (file)
@@ -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'}}
+}