]> granicus.if.org Git - clang/commitdiff
Process attributes in the order they appear in the source code. This make clang
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 7 May 2012 23:58:18 +0000 (23:58 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 7 May 2012 23:58:18 +0000 (23:58 +0000)
match gcc behavior for two conflicting visibilities in the same decl. It also
makes handling of dllimport/dllexport more natural.

As a bonus we now warn on the dllimport in

void __attribute__((dllimport)) foo13();
void __attribute__((dllexport)) foo13();

as does gcc.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156343 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclAttr.cpp
lib/Sema/TargetAttributesSema.cpp
test/Index/complete-with-annotations.cpp
test/Sema/attr-availability.c
test/Sema/attr-visibility.c
test/Sema/dllimport-dllexport.c

index f2d1d19d22da94eda764df96f08ff8be6c25b237..47acdf9456f34a96cb2fdbb1f2079c511144f9ec 100644 (file)
@@ -3986,8 +3986,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
 void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
                                     const AttributeList *AttrList,
                                     bool NonInheritable, bool Inheritable) {
+  SmallVector<const AttributeList*, 4> attrs;
   for (const AttributeList* l = AttrList; l; l = l->getNext()) {
-    ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable);
+    attrs.push_back(l);
+  }
+  for (int i = attrs.size() - 1; i >= 0; --i) {
+    ProcessDeclAttribute(*this, S, D, *attrs[i], NonInheritable, Inheritable);
   }
 
   // GCC accepts
index 8b19be74dd437caa9bff845931b62e8bf2ed57a7..c0746388e59576f5f44222aa9784be2357985afb 100644 (file)
@@ -182,16 +182,6 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
     return;
   }
 
-  // The attribute is also overridden by a subsequent declaration as dllexport.
-  // Warning is emitted.
-  for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
-       nextAttr = nextAttr->getNext()) {
-    if (nextAttr->getKind() == AttributeList::AT_dllexport) {
-      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
-      return;
-    }
-  }
-
   if (D->getAttr<DLLExportAttr>()) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
     return;
@@ -228,6 +218,11 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
     return;
   }
 
+  if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
+    S.Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport";
+    D->dropAttr<DLLImportAttr>();
+  }
+
   D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
 }
 
index afa8d9ed660709abdfba6c5ca3b78b9cb6ded013..3b37e380f3bd7075501aa895c1997e7825b28f30 100644 (file)
@@ -14,7 +14,7 @@ void X::doSomething() {
 }
 
 // CHECK: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34)
-// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("three", "two", "one")
+// CHECK: FieldDecl:{ResultType int}{TypedText field} (35) ("one", "two", "three")
 // CHECK: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (34) ("some annotation")
 // CHECK: FieldDecl:{ResultType int}{TypedText member2} (35) ("another annotation", "some annotation")
 // CHECK: CXXMethod:{ResultType X &}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (34)
index 89252a6cc40bd4c97378e0d6232061f44c3fd92c..a13e351a6e95c0438b9a8ea8e86956545b22f333 100644 (file)
@@ -28,8 +28,8 @@ enum {
 void f4(int) __attribute__((availability(ios,deprecated=3.0)));
 void f4(int) __attribute__((availability(ios,introduced=4.0))); // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}}
 
-void f5(int) __attribute__((availability(ios,deprecated=3.0),  // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}}
-                            availability(ios,introduced=4.0)));
+void f5(int) __attribute__((availability(ios,deprecated=3.0),
+                            availability(ios,introduced=4.0)));  // expected-warning {{feature cannot be deprecated in iOS version 3.0 before it was introduced in version 4.0; attribute ignored}}
 
 void f6(int) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{previous attribute is here}}
 void f6(int) __attribute__((availability(ios,deprecated=4.0))); // expected-warning {{availability does not match previous declaration}}
index 4996dca5be773ea07b7f4d63edda088cd6c135fb..cb549921abe2f0a1329e99e160279e6ad1e6f74b 100644 (file)
@@ -14,3 +14,6 @@ struct __attribute__((visibility("default"))) test4; // expected-error {{visibil
 struct test5;
 struct __attribute__((visibility("hidden"))) test5; // expected-note {{previous attribute is here}}
 struct __attribute__((visibility("default"))) test5; // expected-error {{visibility does not match previous declaration}}
+
+void test6() __attribute__((visibility("hidden"), // expected-note {{previous attribute is here}}
+                            visibility("default"))); // expected-error {{visibility does not match previous declaration}}
index 610059ec9f6b0b10dc4612faabe539abe833196c..4c049026978b16ff5250b50f111c309366a59fc9 100644 (file)
@@ -35,3 +35,6 @@ typedef int __declspec(dllimport) type2; // expected-warning{{'dllimport' attrib
 
 void __declspec(dllimport) foo12();
 void foo12(){} // expected-warning {{'foo12' redeclared without dllimport attribute: previous dllimport ignored}}
+
+void __attribute__((dllimport)) foo13(); // expected-warning{{dllimport attribute ignored}}
+void __attribute__((dllexport)) foo13();