]> granicus.if.org Git - clang/commitdiff
[analyzer] [ARCMT] [NFC] Unify entry point into RetainSummaryManager
authorGeorge Karpenkov <ekarpenkov@apple.com>
Tue, 29 Jan 2019 19:29:33 +0000 (19:29 +0000)
committerGeorge Karpenkov <ekarpenkov@apple.com>
Tue, 29 Jan 2019 19:29:33 +0000 (19:29 +0000)
Just use one single entry point, since we have AnyCall utility now.

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

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

include/clang/Analysis/RetainSummaryManager.h
lib/ARCMigrate/ObjCMT.cpp
lib/Analysis/RetainSummaryManager.cpp
lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp

index 8ec91d741d1f357c868d87fd673d292b0b19c5f1..409f23caf3451b26ea30799e030485cdc9dc43a7 100644 (file)
@@ -203,40 +203,6 @@ public:
   }
 };
 
-/// Encapsulates the retain count semantics on the arguments, return value,
-/// and receiver (if any) of a function/method call.
-///
-/// Note that construction of these objects is not highly efficient.  That
-/// is okay for clients where creating these objects isn't really a bottleneck.
-/// The purpose of the API is to provide something simple.  The actual
-/// static analyzer checker that implements retain/release typestate
-/// tracking uses something more efficient.
-class CallEffects {
-  llvm::SmallVector<ArgEffect, 10> Args;
-  RetEffect Ret;
-  ArgEffect Receiver;
-
-  CallEffects(const RetEffect &R,
-              ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj))
-      : Ret(R), Receiver(Receiver) {}
-
-public:
-  /// Returns the argument effects for a call.
-  ArrayRef<ArgEffect> getArgs() const { return Args; }
-
-  /// Returns the effects on the receiver.
-  ArgEffect getReceiver() const { return Receiver; }
-
-  /// Returns the effect on the return value.
-  RetEffect getReturnValue() const { return Ret; }
-
-  /// Return the CallEfect for a given Objective-C method.
-  static CallEffects getEffect(const ObjCMethodDecl *MD);
-
-  /// Return the CallEfect for a given C/C++ function.
-  static CallEffects getEffect(const FunctionDecl *FD);
-};
-
 /// A key identifying a summary.
 class ObjCSummaryKey {
   IdentifierInfo* II;
@@ -690,9 +656,13 @@ public:
   bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
 
   const RetainSummary *getSummary(AnyCall C,
-                                  bool HasNonZeroCallbackArg,
-                                  bool IsReceiverUnconsumedSelf,
-                                  QualType ReceiverType=QualType());
+                                  bool HasNonZeroCallbackArg=false,
+                                  bool IsReceiverUnconsumedSelf=false,
+                                  QualType ReceiverType={});
+
+  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+
+private:
 
   /// getMethodSummary - This version of getMethodSummary is used to query
   ///  the summary for the current method being analyzed.
@@ -700,9 +670,6 @@ public:
 
   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,
index ed891f295361e2f8aa8af00b637d2e152a13ac6b..f22e03f490f47f3243bd1ae9d9dcf04c239c2ab8 100644 (file)
@@ -64,9 +64,11 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
                             ObjCInstanceTypeFamily OIT_Family = OIT_None);
 
   void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
-  void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
+  void AddCFAnnotations(ASTContext &Ctx,
+                        const RetainSummary *RS,
                         const FunctionDecl *FuncDecl, bool ResultAnnotated);
-  void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
+  void AddCFAnnotations(ASTContext &Ctx,
+                        const RetainSummary *RS,
                         const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
 
   void AnnotateImplicitBridging(ASTContext &Ctx);
@@ -84,6 +86,8 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
 
   bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);
 
+  std::unique_ptr<RetainSummaryManager> Summaries;
+
 public:
   std::string MigrateDir;
   unsigned ASTMigrateActions;
@@ -102,6 +106,14 @@ public:
   llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
   llvm::StringSet<> WhiteListFilenames;
 
+  RetainSummaryManager &getSummaryManager(ASTContext &Ctx) {
+    if (!Summaries)
+      Summaries.reset(new RetainSummaryManager(Ctx,
+                                               /*TrackNSCFObjects=*/true,
+                                               /*TrackOSObjects=*/false));
+    return *Summaries;
+  }
+
   ObjCMigrateASTConsumer(StringRef migrateDir,
                          unsigned astMigrateActions,
                          FileRemapper &remapper,
@@ -1452,12 +1464,12 @@ void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *De
 }
 
 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
-                                              const CallEffects &CE,
+                                              const RetainSummary *RS,
                                               const FunctionDecl *FuncDecl,
                                               bool ResultAnnotated) {
   // Annotate function.
   if (!ResultAnnotated) {
-    RetEffect Ret = CE.getReturnValue();
+    RetEffect Ret = RS->getRetEffect();
     const char *AnnotationString = nullptr;
     if (Ret.getObjKind() == ObjKind::CF) {
       if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
@@ -1477,12 +1489,11 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
       Editor->commit(commit);
     }
   }
-  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
   unsigned i = 0;
   for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
        pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
     const ParmVarDecl *pd = *pi;
-    ArgEffect AE = AEArgs[i];
+    ArgEffect AE = RS->getArg(i);
     if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::CF &&
         !pd->hasAttr<CFConsumedAttr>() &&
         NSAPIObj->isMacroDefined("CF_CONSUMED")) {
@@ -1506,7 +1517,8 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
   if (FuncDecl->hasBody())
     return CF_BRIDGING_NONE;
 
-  CallEffects CE  = CallEffects::getEffect(FuncDecl);
+  const RetainSummary *RS =
+      getSummaryManager(Ctx).getSummary(AnyCall(FuncDecl));
   bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
                                 FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
                                 FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
@@ -1519,7 +1531,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
 
   bool ReturnCFAudited = false;
   if (!FuncIsReturnAnnotated) {
-    RetEffect Ret = CE.getReturnValue();
+    RetEffect Ret = RS->getRetEffect();
     if (Ret.getObjKind() == ObjKind::CF &&
         (Ret.isOwned() || Ret.notOwned()))
       ReturnCFAudited = true;
@@ -1528,14 +1540,12 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
   }
 
   // At this point result type is audited for potential inclusion.
-  // Now, how about argument types.
-  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
   unsigned i = 0;
   bool ArgCFAudited = false;
   for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
        pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
     const ParmVarDecl *pd = *pi;
-    ArgEffect AE = AEArgs[i];
+    ArgEffect AE = RS->getArg(i);
     if ((AE.getKind() == DecRef /*CFConsumed annotated*/ ||
          AE.getKind() == IncRef) && AE.getObjKind() == ObjKind::CF) {
       if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>())
@@ -1545,7 +1555,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
     } else {
       QualType AT = pd->getType();
       if (!AuditedType(AT)) {
-        AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
+        AddCFAnnotations(Ctx, RS, FuncDecl, FuncIsReturnAnnotated);
         return CF_BRIDGING_NONE;
       }
     }
@@ -1567,12 +1577,12 @@ void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
 }
 
 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
-                                              const CallEffects &CE,
+                                              const RetainSummary *RS,
                                               const ObjCMethodDecl *MethodDecl,
                                               bool ResultAnnotated) {
   // Annotate function.
   if (!ResultAnnotated) {
-    RetEffect Ret = CE.getReturnValue();
+    RetEffect Ret = RS->getRetEffect();
     const char *AnnotationString = nullptr;
     if (Ret.getObjKind() == ObjKind::CF) {
       if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
@@ -1604,12 +1614,11 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
       Editor->commit(commit);
     }
   }
-  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
   unsigned i = 0;
   for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
        pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
     const ParmVarDecl *pd = *pi;
-    ArgEffect AE = AEArgs[i];
+    ArgEffect AE = RS->getArg(i);
     if (AE.getKind() == DecRef
         && AE.getObjKind() == ObjKind::CF
         && !pd->hasAttr<CFConsumedAttr>() &&
@@ -1627,7 +1636,9 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
   if (MethodDecl->hasBody() || MethodDecl->isImplicit())
     return;
 
-  CallEffects CE  = CallEffects::getEffect(MethodDecl);
+  const RetainSummary *RS =
+      getSummaryManager(Ctx).getSummary(AnyCall(MethodDecl));
+
   bool MethodIsReturnAnnotated =
       (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
        MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
@@ -1635,7 +1646,7 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
        MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
        MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
 
-  if (CE.getReceiver().getKind() == DecRef &&
+  if (RS->getReceiverEffect().getKind() == DecRef &&
       !MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
       MethodDecl->getMethodFamily() != OMF_init &&
       MethodDecl->getMethodFamily() != OMF_release &&
@@ -1651,27 +1662,25 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
     return;
 
   if (!MethodIsReturnAnnotated) {
-    RetEffect Ret = CE.getReturnValue();
+    RetEffect Ret = RS->getRetEffect();
     if ((Ret.getObjKind() == ObjKind::CF ||
          Ret.getObjKind() == ObjKind::ObjC) &&
         (Ret.isOwned() || Ret.notOwned())) {
-      AddCFAnnotations(Ctx, CE, MethodDecl, false);
+      AddCFAnnotations(Ctx, RS, MethodDecl, false);
       return;
     } else if (!AuditedType(MethodDecl->getReturnType()))
       return;
   }
 
   // At this point result type is either annotated or audited.
-  // Now, how about argument types.
-  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
   unsigned i = 0;
   for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
        pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
     const ParmVarDecl *pd = *pi;
-    ArgEffect AE = AEArgs[i];
+    ArgEffect AE = RS->getArg(i);
     if ((AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>()) ||
         AE.getKind() == IncRef || !AuditedType(pd->getType())) {
-      AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
+      AddCFAnnotations(Ctx, RS, MethodDecl, MethodIsReturnAnnotated);
       return;
     }
   }
index d8b3f818c2467170d4a7cc9b7755ceb8eae2d548..96b5c9eea8628eccb13897d8d76e8fd07dcf7585 100644 (file)
@@ -635,11 +635,14 @@ RetainSummaryManager::getSummary(AnyCall C,
     // FIXME: These calls are currently unsupported.
     return getPersistentStopSummary();
   case AnyCall::ObjCMethod: {
-    const auto *ME = cast<ObjCMessageExpr>(C.getExpr());
-    if (ME->isInstanceMessage())
+    const auto *ME = cast_or_null<ObjCMessageExpr>(C.getExpr());
+    if (!ME) {
+      return getMethodSummary(cast<ObjCMethodDecl>(C.getDecl()));
+    } else if (ME->isInstanceMessage()) {
       Summ = getInstanceMethodSummary(ME, ReceiverType);
-    else
+    } else {
       Summ = getClassMethodSummary(ME);
+    }
     break;
   }
   }
@@ -1238,31 +1241,3 @@ RetainSummaryManager::getMethodSummary(const ObjCMethodDecl *MD) {
 
   return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
 }
-
-CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
-  ASTContext &Ctx = MD->getASTContext();
-  RetainSummaryManager M(Ctx,
-                         /*TrackNSAndCFObjects=*/true,
-                         /*TrackOSObjects=*/false);
-  const RetainSummary *S = M.getMethodSummary(MD);
-  CallEffects CE(S->getRetEffect(), S->getReceiverEffect());
-  unsigned N = MD->param_size();
-  for (unsigned i = 0; i < N; ++i) {
-    CE.Args.push_back(S->getArg(i));
-  }
-  return CE;
-}
-
-CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
-  ASTContext &Ctx = FD->getASTContext();
-  RetainSummaryManager M(Ctx,
-                         /*TrackNSAndCFObjects=*/true,
-                         /*TrackOSObjects=*/false);
-  const RetainSummary *S = M.getFunctionSummary(FD);
-  CallEffects CE(S->getRetEffect());
-  unsigned N = FD->param_size();
-  for (unsigned i = 0; i < N; ++i) {
-    CE.Args.push_back(S->getArg(i));
-  }
-  return CE;
-}
index 1ab4106b857a6291b9c3ea0ff908e1b1cc7e4527..b55ea2a116e884f40acc68396752eb9c018115fa 100644 (file)
@@ -1031,11 +1031,11 @@ ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
 
   // FIXME: What is the convention for blocks? Is there one?
   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
-    const RetainSummary *Summ = Summaries.getMethodSummary(MD);
+    const RetainSummary *Summ = Summaries.getSummary(AnyCall(MD));
     RE = Summ->getRetEffect();
   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
     if (!isa<CXXMethodDecl>(FD)) {
-      const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
+      const RetainSummary *Summ = Summaries.getSummary(AnyCall(FD));
       RE = Summ->getRetEffect();
     }
   }
@@ -1324,7 +1324,7 @@ void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
     return;
 
   ProgramStateRef state = Ctx.getState();
-  const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
+  const RetainSummary *FunctionSummary = SmrMgr.getSummary(AnyCall(FD));
   ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
 
   for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {