]> granicus.if.org Git - clang/commitdiff
Properly move attributes to the decl spec when applying them there.
authorJohn McCall <rjmccall@apple.com>
Sat, 26 Mar 2011 01:39:56 +0000 (01:39 +0000)
committerJohn McCall <rjmccall@apple.com>
Sat, 26 Mar 2011 01:39:56 +0000 (01:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128324 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaType.cpp
test/SemaObjC/weak-attr-ivar.m

index 53242294ac1b8247f4ad45fa7a4e109aaa26b733..d0b3fe70a20460eeb179fa08865918e59bea2164 100644 (file)
@@ -138,6 +138,9 @@ namespace {
     /// Whether there are non-trivial modifications to the decl spec.
     bool trivial;
 
+    /// Whether we saved the attributes in the decl spec.
+    bool hasSavedAttrs;
+
     /// The original set of attributes on the DeclSpec.
     llvm::SmallVector<AttributeList*, 2> savedAttrs;
 
@@ -149,7 +152,7 @@ namespace {
     TypeProcessingState(Sema &sema, Declarator &declarator)
       : sema(sema), declarator(declarator),
         chunkIndex(declarator.getNumTypeObjects()),
-        trivial(true) {}
+        trivial(true), hasSavedAttrs(false) {}
 
     Sema &getSema() const {
       return sema;
@@ -178,13 +181,14 @@ namespace {
     /// Save the current set of attributes on the DeclSpec.
     void saveDeclSpecAttrs() {
       // Don't try to save them multiple times.
-      if (!savedAttrs.empty()) return;
+      if (hasSavedAttrs) return;
 
       DeclSpec &spec = getMutableDeclSpec();
       for (AttributeList *attr = spec.getAttributes().getList(); attr;
              attr = attr->getNext())
         savedAttrs.push_back(attr);
       trivial &= savedAttrs.empty();
+      hasSavedAttrs = true;
     }
 
     /// Record that we had nowhere to put the given type attribute.
@@ -214,7 +218,13 @@ namespace {
     }
 
     void restoreDeclSpecAttrs() {
-      assert(!savedAttrs.empty());
+      assert(hasSavedAttrs);
+
+      if (savedAttrs.empty()) {
+        getMutableDeclSpec().getAttributes().set(0);
+        return;
+      }
+
       getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
       for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
         savedAttrs[i]->setNext(savedAttrs[i+1]);
@@ -360,8 +370,15 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
   // That might actually be the decl spec if we weren't blocked by
   // anything in the declarator.
   if (considerDeclSpec) {
-    if (handleObjCPointerTypeAttr(state, attr, declSpecType))
+    if (handleObjCPointerTypeAttr(state, attr, declSpecType)) {
+      // Splice the attribute into the decl spec.  Prevents the
+      // attribute from being applied multiple times and gives
+      // the source-location-filler something to work with.
+      state.saveDeclSpecAttrs();
+      moveAttrFromListToList(attr, declarator.getAttrListRef(),
+               declarator.getMutableDeclSpec().getAttributes().getListRef());
       return;
+    }
   }
 
   // Otherwise, if we found an appropriate chunk, splice the attribute
index d5bbb01902db459899293b15457d68c1827d731a..e3d96da13bb792a8a878186baae04c17f29d8b56 100644 (file)
@@ -72,3 +72,13 @@ typedef enum { Foo_HUH_NONE } FooHUHCode;
 }
 @end
 
+// rdar://problem/9123040
+@interface Test1 {
+@public
+  id ivar __attribute__((objc_gc(weak)));
+}
+@property (assign) id prop __attribute((objc_gc(weak)));
+@end
+void test1(Test1 *t) {
+  id *(__attribute__((objc_gc(strong))) x) = &t->ivar; // expected-warning {{initializing '__strong id *' with an expression of type '__weak id *' discards qualifiers}}
+}