]> granicus.if.org Git - clang/commitdiff
[analyzer] [RetainCountChecker] Produce a correct message when OSTypeAlloc is used
authorGeorge Karpenkov <ekarpenkov@apple.com>
Fri, 18 Jan 2019 03:12:48 +0000 (03:12 +0000)
committerGeorge Karpenkov <ekarpenkov@apple.com>
Fri, 18 Jan 2019 03:12:48 +0000 (03:12 +0000)
Differential Revision: https://reviews.llvm.org/D56820

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

lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
test/Analysis/os_object_base.h
test/Analysis/osobject-retain-release.cpp

index cda1a928de1340a3d11299ce03a7129321fc838d..85b97ac9c02537dec0426b563918e86bfdb15d6e 100644 (file)
@@ -132,6 +132,32 @@ static Optional<unsigned> findArgIdxOfSymbol(ProgramStateRef CurrSt,
   return None;
 }
 
+Optional<std::string> findMetaClassAlloc(const Expr *Callee) {
+  if (const auto *ME = dyn_cast<MemberExpr>(Callee)) {
+    if (ME->getMemberDecl()->getNameAsString() != "alloc")
+      return None;
+    const Expr *This = ME->getBase()->IgnoreParenImpCasts();
+    if (const auto *DRE = dyn_cast<DeclRefExpr>(This)) {
+      const ValueDecl *VD = DRE->getDecl();
+      if (VD->getNameAsString() != "metaClass")
+        return None;
+
+      if (const auto *RD = dyn_cast<CXXRecordDecl>(VD->getDeclContext()))
+        return RD->getNameAsString();
+
+    }
+  }
+  return None;
+}
+
+std::string findAllocatedObjectName(const Stmt *S,
+                                    QualType QT) {
+  if (const auto *CE = dyn_cast<CallExpr>(S))
+    if (auto Out = findMetaClassAlloc(CE->getCallee()))
+      return *Out;
+  return getPrettyTypeName(QT);
+}
+
 static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
                                            const LocationContext *LCtx,
                                            const RefVal &CurrV, SymbolRef &Sym,
@@ -189,7 +215,7 @@ static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
     os << "a Core Foundation object of type '"
        << Sym->getType().getAsString() << "' with a ";
   } else if (CurrV.getObjKind() == ObjKind::OS) {
-    os << "an OSObject of type '" << getPrettyTypeName(Sym->getType())
+    os << "an OSObject of type '" << findAllocatedObjectName(S, Sym->getType())
        << "' with a ";
   } else if (CurrV.getObjKind() == ObjKind::Generalized) {
     os << "an object of type '" << Sym->getType().getAsString()
index 997d0d29588921451200d350b85df3d62fb599ea..e388dddd58f170e3e3c56b243a2b89f76d41f6aa 100644 (file)
@@ -47,7 +47,7 @@ struct OSObject : public OSMetaClassBase {
 };
 
 struct OSMetaClass : public OSMetaClassBase {
-  virtual OSObject * alloc();
+  virtual OSObject * alloc() const;
   virtual ~OSMetaClass(){}
 };
 
index af40a55aef2bc1a51376af3ca6610d8c6bcb91dc..3aaaab3bef020f55aa912ef7e1bb977a7a9486a3 100644 (file)
@@ -627,3 +627,10 @@ void test_smart_ptr_no_leak() {
   }
   obj->release();
 }
+
+void test_ostypealloc_correct_diagnostic_name() {
+  OSArray *arr = OSTypeAlloc(OSArray); // expected-note{{Call to method 'OSMetaClass::alloc' returns an OSObject of type 'OSArray' with a +1 retain count}}
+  arr->retain(); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
+  arr->release(); // expected-note{{Reference count decremented. The object now has a +1 retain count}}
+} // expected-note{{Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1}}
+  // expected-warning@-1{{Potential leak of an object stored into 'arr'}}