diff options
author | dmaclach <dmaclach@gmail.com> | 2024-03-21 11:22:35 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-21 14:22:35 -0400 |
commit | 3fefeafa49299ef924414bfa1b678e0f656b3618 (patch) | |
tree | 81553d760856f2eba501e687d696ff2357f42953 | |
parent | 999d4f840777bf8de26d45947192aa0728edc0fb (diff) | |
download | llvm-3fefeafa49299ef924414bfa1b678e0f656b3618.zip llvm-3fefeafa49299ef924414bfa1b678e0f656b3618.tar.gz llvm-3fefeafa49299ef924414bfa1b678e0f656b3618.tar.bz2 |
[OBJC] Allow __attribute__((NSObject)) types be used as lightweight generic specifiers (#84593)
As per
https://clang.llvm.org/docs/AutomaticReferenceCounting.html#retainable-object-pointers,
types with `__attribute__((NSObject))` are retainable, and thus should
be eligible to be used as lightweight generic specifiers.
Fix for #84592 84592
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 5 | ||||
-rw-r--r-- | clang/test/SemaObjC/attr-objc-NSObject.m | 23 |
2 files changed, 28 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 7b14323..d7521a5 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1018,6 +1018,11 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, return type; } + // Types that have __attribute__((NSObject)) are permitted. + if (typeArg->isObjCNSObjectType()) { + continue; + } + // Dependent types will be checked at instantiation time. if (typeArg->isDependentType()) { continue; diff --git a/clang/test/SemaObjC/attr-objc-NSObject.m b/clang/test/SemaObjC/attr-objc-NSObject.m new file mode 100644 index 0000000..76a01dc --- /dev/null +++ b/clang/test/SemaObjC/attr-objc-NSObject.m @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -verify -Wno-objc-root-class -fsyntax-only %s + +@interface NSArray<__covariant ObjectType> +- (void)containsObject:(ObjectType)anObject; // expected-note {{passing argument to parameter 'anObject' here}} +- (void)description; +@end + +typedef __attribute__((NSObject)) struct Foo *FooRef; +typedef struct Bar *BarRef; + +void good() { + FooRef object; + NSArray<FooRef> *array; + [array containsObject:object]; + [object description]; +} + +void bad() { + BarRef object; + NSArray<BarRef> *array; // expected-error {{type argument 'BarRef' (aka 'struct Bar *') is neither an Objective-C object nor a block type}} + [array containsObject:object]; // expected-warning {{incompatible pointer types sending 'BarRef' (aka 'struct Bar *') to parameter of type 'id'}} + [object description]; // expected-warning {{receiver type 'BarRef' (aka 'struct Bar *') is not 'id' or interface pointer, consider casting it to 'id'}} +} |