diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 25 | ||||
-rw-r--r-- | clang/test/SemaObjC/weak-attr-ivar.m | 10 |
2 files changed, 31 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 53242294ac1..d0b3fe70a20 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -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 diff --git a/clang/test/SemaObjC/weak-attr-ivar.m b/clang/test/SemaObjC/weak-attr-ivar.m index d5bbb01902d..e3d96da13bb 100644 --- a/clang/test/SemaObjC/weak-attr-ivar.m +++ b/clang/test/SemaObjC/weak-attr-ivar.m @@ -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}} +} |