[analyzer] Port RetainSummaryManager to the new AnyCall interface, decouple ARCMT...
authorGeorge Karpenkov <ekarpenkov@apple.com>
Fri, 25 Jan 2019 01:24:04 +0000 (01:24 +0000)
committerGeorge Karpenkov <ekarpenkov@apple.com>
Fri, 25 Jan 2019 01:24:04 +0000 (01:24 +0000)
rdar://19694750

Differential Revision: https://reviews.llvm.org/D57127

llvm-svn: 352149

clang/include/clang/Analysis/RetainSummaryManager.h [moved from clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h with 93% similarity]
clang/lib/ARCMigrate/CMakeLists.txt
clang/lib/ARCMigrate/ObjCMT.cpp
clang/lib/Analysis/CMakeLists.txt
clang/lib/Analysis/RetainSummaryManager.cpp [moved from clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp with 94% similarity]
clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
clang/lib/StaticAnalyzer/Core/CMakeLists.txt

 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER
-#define LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER
+#ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_H
+#define LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_H
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ParentMap.h"
+#include "clang/Analysis/AnyCall.h"
 #include "clang/Analysis/SelectorExtras.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "llvm/ADT/STLExtras.h"
 
-//===----------------------------------------------------------------------===//
-// Adapters for FoldingSet.
-//===----------------------------------------------------------------------===//
-
 using namespace clang;
-using namespace ento;
 
 namespace clang {
 namespace ento {
@@ -262,9 +258,13 @@ public:
 } // end namespace ento
 } // end namespace clang
 
+using namespace ento;
 
 namespace llvm {
 
+//===----------------------------------------------------------------------===//
+// Adapters for FoldingSet.
+//===----------------------------------------------------------------------===//
 template <> struct FoldingSetTrait<ArgEffect> {
 static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
   ID.AddInteger((unsigned) X.getKind());
@@ -653,19 +653,15 @@ class RetainSummaryManager {
                                   RetainSummaryTemplate &Template);
 
 public:
-  RetainSummaryManager(ASTContext &ctx,
-                       bool usesARC,
-                       bool trackObjCAndCFObjects,
+  RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects,
                        bool trackOSObjects)
-   : Ctx(ctx),
-     ARCEnabled(usesARC),
-     TrackObjCAndCFObjects(trackObjCAndCFObjects),
-     TrackOSObjects(trackOSObjects),
-     AF(BPAlloc),
-     ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC)
-                               : RetEffect::MakeOwned(ObjKind::ObjC)),
-     ObjCInitRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC)
-                               : RetEffect::MakeOwnedWhenTrackedReceiver()) {
+      : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount),
+        TrackObjCAndCFObjects(trackObjCAndCFObjects),
+        TrackOSObjects(trackOSObjects), AF(BPAlloc),
+        ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
+                                 : RetEffect::MakeOwned(ObjKind::ObjC)),
+        ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
+                                : RetEffect::MakeOwnedWhenTrackedReceiver()) {
     InitializeClassMethodSummaries();
     InitializeMethodSummaries();
   }
@@ -693,43 +689,29 @@ public:
 
   bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
 
-  const RetainSummary *getSummary(const CallEvent &Call,
+  const RetainSummary *getSummary(AnyCall C,
+                                  bool HasNonZeroCallbackArg,
+                                  bool IsReceiverUnconsumedSelf,
                                   QualType ReceiverType=QualType());
 
+  /// getMethodSummary - This version of getMethodSummary is used to query
+  ///  the summary for the current method being analyzed.
+  const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD);
+
   const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
 
+  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+
+private:
   const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
                                         const ObjCMethodDecl *MD,
                                         QualType RetTy,
                                         ObjCMethodSummariesTy &CachedSummaries);
 
   const RetainSummary *
-  getInstanceMethodSummary(const ObjCMethodCall &M,
-                           QualType ReceiverType);
-
-  const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
-    assert(!M.isInstanceMessage());
-    const ObjCInterfaceDecl *Class = M.getReceiverInterface();
-
-    return getMethodSummary(M.getSelector(), Class, M.getDecl(),
-                            M.getResultType(), ObjCClassMethodSummaries);
-  }
-
-  /// getMethodSummary - This version of getMethodSummary is used to query
-  ///  the summary for the current method being analyzed.
-  const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
-    const ObjCInterfaceDecl *ID = MD->getClassInterface();
-    Selector S = MD->getSelector();
-    QualType ResultTy = MD->getReturnType();
+  getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType);
 
-    ObjCMethodSummariesTy *CachedSummaries;
-    if (MD->isInstanceMethod())
-      CachedSummaries = &ObjCMethodSummaries;
-    else
-      CachedSummaries = &ObjCClassMethodSummaries;
-
-    return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
-  }
+  const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME);
 
   const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
                                                 Selector S, QualType RetTy);
@@ -744,13 +726,10 @@ public:
   void updateSummaryFromAnnotations(const RetainSummary *&Summ,
                                     const FunctionDecl *FD);
 
-
   void updateSummaryForCall(const RetainSummary *&Summ,
-                            const CallEvent &Call);
-
-  bool isARCEnabled() const { return ARCEnabled; }
-
-  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+                            AnyCall C,
+                            bool HasNonZeroCallbackArg,
+                            bool IsReceiverUnconsumedSelf);
 
   /// Determine whether a declaration {@code D} of correspondent type (return
   /// type for functions/methods) {@code QT} has any of the given attributes,
index efdff27..619328c 100644 (file)
@@ -34,6 +34,4 @@ add_clang_library(clangARCMigrate
   clangRewrite
   clangSema
   clangSerialization
-  clangStaticAnalyzerCheckers
-  clangStaticAnalyzerCore
   )
index 34e92ab..ed891f2 100644 (file)
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Transforms.h"
+#include "clang/Analysis/RetainSummaryManager.h"
 #include "clang/ARCMigrate/ARCMT.h"
 #include "clang/ARCMigrate/ARCMTActions.h"
 #include "clang/AST/ASTConsumer.h"
@@ -26,7 +27,6 @@
 #include "clang/Lex/PPConditionalDirectiveRecord.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Path.h"
index 5345a56..940a3df 100644 (file)
@@ -21,6 +21,7 @@ add_clang_library(clangAnalysis
   PostOrderCFGView.cpp
   ProgramPoint.cpp
   ReachableCode.cpp
+  RetainSummaryManager.cpp
   ThreadSafety.cpp
   ThreadSafetyCommon.cpp
   ThreadSafetyLogical.cpp
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Analysis/RetainSummaryManager.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
@@ -558,8 +558,11 @@ static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
 }
 
 void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
-                                                const CallEvent &Call) {
-  if (Call.hasNonZeroCallbackArg()) {
+                                                AnyCall C,
+                                                bool HasNonZeroCallbackArg,
+                                                bool IsReceiverUnconsumedSelf) {
+
+  if (HasNonZeroCallbackArg) {
     ArgEffect RecEffect =
       getStopTrackingHardEquivalent(S->getReceiverEffect());
     ArgEffect DefEffect =
@@ -580,8 +583,8 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
     // Special cases where the callback argument CANNOT free the return value.
     // This can generally only happen if we know that the callback will only be
     // called when the return value is already being deallocated.
-    if (const SimpleFunctionCall *FC = dyn_cast<SimpleFunctionCall>(&Call)) {
-      if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {
+    if (C.getKind() == AnyCall::Function) {
+      if (const IdentifierInfo *Name = C.getIdentifier()) {
         // When the CGBitmapContext is deallocated, the callback here will free
         // the associated data buffer.
         // The callback in dispatch_data_create frees the buffer, but not
@@ -607,50 +610,42 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
   // Note, we don't want to just stop tracking the value since we want the
   // RetainCount checker to report leaks and use-after-free if SelfInit checker
   // is turned off.
-  if (const ObjCMethodCall *MC = dyn_cast<ObjCMethodCall>(&Call)) {
-    if (MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper()) {
-
-      // Check if the message is not consumed, we know it will not be used in
-      // an assignment, ex: "self = [super init]".
-      const Expr *ME = MC->getOriginExpr();
-      const LocationContext *LCtx = MC->getLocationContext();
-      ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();
-      if (!PM.isConsumedExpr(ME)) {
-        RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
-        ModifiableSummaryTemplate->setReceiverEffect(ArgEffect(DoNothing));
-        ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
-      }
-    }
+  if (IsReceiverUnconsumedSelf) {
+    RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
+    ModifiableSummaryTemplate->setReceiverEffect(ArgEffect(DoNothing));
+    ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
   }
 }
 
 const RetainSummary *
-RetainSummaryManager::getSummary(const CallEvent &Call,
+RetainSummaryManager::getSummary(AnyCall C,
+                                 bool HasNonZeroCallbackArg,
+                                 bool IsReceiverUnconsumedSelf,
                                  QualType ReceiverType) {
   const RetainSummary *Summ;
-  switch (Call.getKind()) {
-  case CE_Function:
-  case CE_CXXMember:
-  case CE_CXXMemberOperator:
-  case CE_CXXConstructor:
-  case CE_CXXAllocator:
-    Summ = getFunctionSummary(cast_or_null<FunctionDecl>(Call.getDecl()));
+  switch (C.getKind()) {
+  case AnyCall::Function:
+  case AnyCall::Constructor:
+  case AnyCall::Allocator:
+  case AnyCall::Deallocator:
+    Summ = getFunctionSummary(cast_or_null<FunctionDecl>(C.getDecl()));
     break;
-  case CE_Block:
-  case CE_CXXDestructor:
+  case AnyCall::Block:
+  case AnyCall::Destructor:
     // FIXME: These calls are currently unsupported.
     return getPersistentStopSummary();
-  case CE_ObjCMessage: {
-    const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
-    if (Msg.isInstanceMessage())
-      Summ = getInstanceMethodSummary(Msg, ReceiverType);
+  case AnyCall::ObjCMethod: {
+    const auto *ME = cast<ObjCMessageExpr>(C.getExpr());
+    if (ME->isInstanceMessage())
+      Summ = getInstanceMethodSummary(ME, ReceiverType);
     else
-      Summ = getClassMethodSummary(Msg);
+      Summ = getClassMethodSummary(ME);
     break;
   }
   }
 
-  updateSummaryForCall(Summ, Call);
+  updateSummaryForCall(Summ, C, HasNonZeroCallbackArg,
+                       IsReceiverUnconsumedSelf);
 
   assert(Summ && "Unknown call type?");
   return Summ;
@@ -1067,8 +1062,17 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
                               ArgEffect(ReceiverEff), ArgEffect(MayEscape));
 }
 
+const RetainSummary *
+RetainSummaryManager::getClassMethodSummary(const ObjCMessageExpr *ME) {
+  assert(!ME->isInstanceMessage());
+  const ObjCInterfaceDecl *Class = ME->getReceiverInterface();
+
+  return getMethodSummary(ME->getSelector(), Class, ME->getMethodDecl(),
+                          ME->getType(), ObjCClassMethodSummaries);
+}
+
 const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
-    const ObjCMethodCall &Msg,
+    const ObjCMessageExpr *ME,
     QualType ReceiverType) {
   const ObjCInterfaceDecl *ReceiverClass = nullptr;
 
@@ -1080,18 +1084,18 @@ const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
 
   // If we don't know what kind of object this is, fall back to its static type.
   if (!ReceiverClass)
-    ReceiverClass = Msg.getReceiverInterface();
+    ReceiverClass = ME->getReceiverInterface();
 
   // FIXME: The receiver could be a reference to a class, meaning that
   //  we should use the class method.
   // id x = [NSObject class];
   // [x performSelector:... withObject:... afterDelay:...];
-  Selector S = Msg.getSelector();
-  const ObjCMethodDecl *Method = Msg.getDecl();
+  Selector S = ME->getSelector();
+  const ObjCMethodDecl *Method = ME->getMethodDecl();
   if (!Method && ReceiverClass)
     Method = ReceiverClass->getInstanceMethod(S);
 
-  return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
+  return getMethodSummary(S, ReceiverClass, Method, ME->getType(),
                           ObjCMethodSummaries);
 }
 
@@ -1220,10 +1224,24 @@ void RetainSummaryManager::InitializeMethodSummaries() {
   addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");
 }
 
+const RetainSummary *
+RetainSummaryManager::getMethodSummary(const ObjCMethodDecl *MD) {
+  const ObjCInterfaceDecl *ID = MD->getClassInterface();
+  Selector S = MD->getSelector();
+  QualType ResultTy = MD->getReturnType();
+
+  ObjCMethodSummariesTy *CachedSummaries;
+  if (MD->isInstanceMethod())
+    CachedSummaries = &ObjCMethodSummaries;
+  else
+    CachedSummaries = &ObjCClassMethodSummaries;
+
+  return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
+}
+
 CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
   ASTContext &Ctx = MD->getASTContext();
-  LangOptions L = Ctx.getLangOpts();
-  RetainSummaryManager M(Ctx, L.ObjCAutoRefCount,
+  RetainSummaryManager M(Ctx,
                          /*TrackNSAndCFObjects=*/true,
                          /*TrackOSObjects=*/false);
   const RetainSummary *S = M.getMethodSummary(MD);
@@ -1237,8 +1255,7 @@ CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
 
 CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
   ASTContext &Ctx = FD->getASTContext();
-  LangOptions L = Ctx.getLangOpts();
-  RetainSummaryManager M(Ctx, L.ObjCAutoRefCount,
+  RetainSummaryManager M(Ctx,
                          /*TrackNSAndCFObjects=*/true,
                          /*TrackOSObjects=*/false);
   const RetainSummary *S = M.getFunctionSummary(FD);
index a72f09f..dc8609f 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "RetainCountChecker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 
 using namespace clang;
 using namespace ento;
@@ -326,6 +327,31 @@ void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
   C.addTransition(State);
 }
 
+static bool isReceiverUnconsumedSelf(const CallEvent &Call) {
+  if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) {
+
+    // Check if the message is not consumed, we know it will not be used in
+    // an assignment, ex: "self = [super init]".
+    return MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper() &&
+           !Call.getLocationContext()
+                ->getAnalysisDeclContext()
+                ->getParentMap()
+                .isConsumedExpr(Call.getOriginExpr());
+  }
+  return false;
+}
+
+const static RetainSummary *getSummary(RetainSummaryManager &Summaries,
+                                       const CallEvent &Call,
+                                       QualType ReceiverType) {
+  const Expr *CE = Call.getOriginExpr();
+  AnyCall C =
+      CE ? *AnyCall::forExpr(CE)
+         : AnyCall::forDestructorCall(cast<CXXDestructorDecl>(Call.getDecl()));
+  return Summaries.getSummary(C, Call.hasNonZeroCallbackArg(),
+                              isReceiverUnconsumedSelf(Call), ReceiverType);
+}
+
 void RetainCountChecker::checkPostCall(const CallEvent &Call,
                                        CheckerContext &C) const {
   RetainSummaryManager &Summaries = getSummaryManager(C);
@@ -341,7 +367,7 @@ void RetainCountChecker::checkPostCall(const CallEvent &Call,
     }
   }
 
-  const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType);
+  const RetainSummary *Summ = getSummary(Summaries, Call, ReceiverType);
 
   if (C.wasInlined) {
     processSummaryOfInlined(*Summ, Call, C);
index 8e74f6c..775cd21 100644 (file)
@@ -21,6 +21,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ParentMap.h"
 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Analysis/RetainSummaryManager.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Analysis/SelectorExtras.h"
@@ -32,7 +33,6 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/ImmutableList.h"
@@ -275,15 +275,9 @@ public:
   RetainCountChecker() {};
 
   RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
-    // FIXME: We don't support ARC being turned on and off during one analysis.
-    // (nor, for that matter, do we support changing ASTContexts)
-    bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
-    if (!Summaries) {
-      Summaries.reset(new RetainSummaryManager(
-          Ctx, ARCEnabled, TrackObjCAndCFObjects, TrackOSObjects));
-    } else {
-      assert(Summaries->isARCEnabled() == ARCEnabled);
-    }
+    if (!Summaries)
+      Summaries.reset(
+          new RetainSummaryManager(Ctx, TrackObjCAndCFObjects, TrackOSObjects));
     return *Summaries;
   }
 
index e0b53e4..ef3c75f 100644 (file)
 #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
 #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
 
+#include "clang/Analysis/RetainSummaryManager.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 
 namespace clang {
 namespace ento {
index 167f78a..80047f4 100644 (file)
@@ -43,7 +43,6 @@ add_clang_library(clangStaticAnalyzerCore
   RangeConstraintManager.cpp
   RangedConstraintManager.cpp
   RegionStore.cpp
-  RetainSummaryManager.cpp
   SarifDiagnostics.cpp
   SimpleConstraintManager.cpp
   SimpleSValBuilder.cpp