diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index e5c74bbaf3d6b..383977105a942 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -264,9 +264,21 @@ void RetainTypeChecker::visitTypedef(const TypedefDecl *TD) { } } +bool isNSApplicationCocoaObjectRef(const QualType QT) { + if (const ObjCObjectPointerType *PT = QT->getAs()) { + const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); + if (ID && ID->getIdentifier()->getName() == "NSApplication") + return true; + } + return false; +} + bool RetainTypeChecker::isUnretained(const QualType QT, bool ignoreARC) { - if (ento::cocoa::isCocoaObjectRef(QT) && (!IsARCEnabled || ignoreARC)) + if (ento::cocoa::isCocoaObjectRef(QT) && (!IsARCEnabled || ignoreARC)) { + if (isNSApplicationCocoaObjectRef(QT)) + return false; return true; + } if (auto *RT = dyn_cast_or_null( QT.getCanonicalType()->getPointeeType().getTypePtrOrNull())) return CFPointees.contains(RT); @@ -281,8 +293,11 @@ std::optional isUnretained(const QualType T, bool IsARCEnabled) { } } if ((ento::cocoa::isCocoaObjectRef(T) && !IsARCEnabled) || - ento::coreFoundation::isCFObjectRef(T)) + ento::coreFoundation::isCFObjectRef(T)) { + if (isNSApplicationCocoaObjectRef(T)) + return false; return true; + } // RetainPtr strips typedef for CF*Ref. Manually check for struct __CF* types. auto CanonicalType = T.getCanonicalType(); diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h index 39dee1746158b..817f78252225c 100644 --- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h @@ -132,6 +132,11 @@ __attribute__((objc_root_class)) + (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt; @end +@interface NSApplication : NSObject +@end + +NSApplication * NSApp; + @interface NSArray : NSObject - (NSUInteger)count; - (NSEnumerator *)objectEnumerator; diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm index c9d2fe861bb49..dcf5474be43fe 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm @@ -565,6 +565,7 @@ @interface TestObject : NSObject - (void)doWork:(NSString *)msg, ...; - (void)doWorkOnSelf; - (SomeObj *)getSomeObj; +- (void)callNSApp; @end @implementation TestObject @@ -600,4 +601,8 @@ - (NSString *)convertImage { RetainPtr image = [self createImage]; return stringForImage(image.get()); } + +- (void)callNSApp { + [NSApp foo]; +} @end