aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2018-08-18 03:22:11 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2018-08-18 03:22:11 +0000
commite6554b83e1b0d110f74b77594770e483dcc62e4f (patch)
tree2fe2ab90da7d1b889d4e210c5d6b85933eeeafea
parenta786521fa66c72edd308baff0c08961b6d964fb1 (diff)
Revert "[analyzer] [NFC] Split up RetainSummaryManager from RetainCountChecker"
This reverts commit a786521fa66c72edd308baff0c08961b6d964fb1. Bots haven't caught up yet, but broke modules build with: ../tools/clang/include/clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h:18:10: fatal error: cyclic dependency in module 'Clang_StaticAnalyzer_Core': Clang_StaticAnalyzer_Core -> Clang_Analysis -> Clang_StaticAnalyzer_Checkers -> Clang_StaticAnalyzer_Core ^ git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@340117 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Analysis/ObjCRetainCount.h231
-rw-r--r--lib/ARCMigrate/CMakeLists.txt1
-rw-r--r--lib/ARCMigrate/ObjCMT.cpp4
-rw-r--r--lib/Analysis/CMakeLists.txt1
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/CMakeLists.txt1
-rw-r--r--lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp54
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h6
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h2
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp (renamed from lib/Analysis/RetainSummaryManager.cpp)58
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h (renamed from include/clang/Analysis/RetainSummaryManager.h)234
-rw-r--r--lib/StaticAnalyzer/Checkers/SelectorExtras.h (renamed from include/clang/StaticAnalyzer/Checkers/SelectorExtras.h)7
-rw-r--r--lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp2
14 files changed, 335 insertions, 270 deletions
diff --git a/include/clang/Analysis/ObjCRetainCount.h b/include/clang/Analysis/ObjCRetainCount.h
new file mode 100644
index 0000000000..9dff1ea12a
--- /dev/null
+++ b/include/clang/Analysis/ObjCRetainCount.h
@@ -0,0 +1,231 @@
+//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the core data structures for retain count "summaries"
+// for Objective-C and Core Foundation APIs. These summaries are used
+// by the static analyzer to summarize the retain/release effects of
+// function and method calls. This drives a path-sensitive typestate
+// analysis in the static analyzer, but can also potentially be used by
+// other clients.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
+#define LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+class FunctionDecl;
+class ObjCMethodDecl;
+
+namespace ento { namespace objc_retain {
+
+/// An ArgEffect summarizes the retain count behavior on an argument or receiver
+/// to a function or method.
+enum ArgEffect {
+ /// There is no effect.
+ DoNothing,
+
+ /// The argument is treated as if an -autorelease message had been sent to
+ /// the referenced object.
+ Autorelease,
+
+ /// The argument is treated as if an -dealloc message had been sent to
+ /// the referenced object.
+ Dealloc,
+
+ /// The argument has its reference count decreased by 1. This is as
+ /// if CFRelease has been called on the argument.
+ DecRef,
+
+ /// The argument has its reference count decreased by 1. This is as
+ /// if a -release message has been sent to the argument. This differs
+ /// in behavior from DecRef when GC is enabled.
+ DecRefMsg,
+
+ /// The argument has its reference count decreased by 1 to model
+ /// a transferred bridge cast under ARC.
+ DecRefBridgedTransferred,
+
+ /// The argument has its reference count increased by 1. This is as
+ /// if a -retain message has been sent to the argument. This differs
+ /// in behavior from IncRef when GC is enabled.
+ IncRefMsg,
+
+ /// The argument has its reference count increased by 1. This is as
+ /// if CFRetain has been called on the argument.
+ IncRef,
+
+ /// Used to mark an argument as collectible in GC mode, currently a noop.
+ MakeCollectable,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +0 value or NULL.
+ UnretainedOutParameter,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +1 value or NULL.
+ RetainedOutParameter,
+
+ /// The argument is treated as potentially escaping, meaning that
+ /// even when its reference count hits 0 it should be treated as still
+ /// possibly being alive as someone else *may* be holding onto the object.
+ MayEscape,
+
+ /// All typestate tracking of the object ceases. This is usually employed
+ /// when the effect of the call is completely unknown.
+ StopTracking,
+
+ /// All typestate tracking of the object ceases. Unlike StopTracking,
+ /// this is also enforced when the method body is inlined.
+ ///
+ /// In some cases, we obtain a better summary for this checker
+ /// by looking at the call site than by inlining the function.
+ /// Signifies that we should stop tracking the symbol even if
+ /// the function is inlined.
+ StopTrackingHard,
+
+ /// Performs the combined functionality of DecRef and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefAndStopTrackingHard,
+
+ /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefMsgAndStopTrackingHard
+};
+
+/// RetEffect summarizes a call's retain/release behavior with respect
+/// to its return value.
+class RetEffect {
+public:
+ enum Kind {
+ /// Indicates that no retain count information is tracked for
+ /// the return value.
+ NoRet,
+ /// Indicates that the returned value is an owned (+1) symbol.
+ OwnedSymbol,
+ /// Indicates that the returned value is an object with retain count
+ /// semantics but that it is not owned (+0). This is the default
+ /// for getters, etc.
+ NotOwnedSymbol,
+ /// Indicates that the object is not owned and controlled by the
+ /// Garbage collector.
+ GCNotOwnedSymbol,
+ /// Indicates that the return value is an owned object when the
+ /// receiver is also a tracked object.
+ OwnedWhenTrackedReceiver,
+ // Treat this function as returning a non-tracked symbol even if
+ // the function has been inlined. This is used where the call
+ // site summary is more presise than the summary indirectly produced
+ // by inlining the function
+ NoRetHard
+ };
+
+ /// Determines the object kind of a tracked object.
+ enum ObjKind {
+ /// Indicates that the tracked object is a CF object. This is
+ /// important between GC and non-GC code.
+ CF,
+ /// Indicates that the tracked object is an Objective-C object.
+ ObjC,
+ /// Indicates that the tracked object could be a CF or Objective-C object.
+ AnyObj,
+ /// Indicates that the tracked object is a generalized object.
+ Generalized
+ };
+
+private:
+ Kind K;
+ ObjKind O;
+
+ RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
+
+public:
+ Kind getKind() const { return K; }
+
+ ObjKind getObjKind() const { return O; }
+
+ bool isOwned() const {
+ return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
+ }
+
+ bool notOwned() const {
+ return K == NotOwnedSymbol;
+ }
+
+ bool operator==(const RetEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+
+ static RetEffect MakeOwnedWhenTrackedReceiver() {
+ return RetEffect(OwnedWhenTrackedReceiver, ObjC);
+ }
+
+ static RetEffect MakeOwned(ObjKind o) {
+ return RetEffect(OwnedSymbol, o);
+ }
+ static RetEffect MakeNotOwned(ObjKind o) {
+ return RetEffect(NotOwnedSymbol, o);
+ }
+ static RetEffect MakeGCNotOwned() {
+ return RetEffect(GCNotOwnedSymbol, ObjC);
+ }
+ static RetEffect MakeNoRet() {
+ return RetEffect(NoRet);
+ }
+ static RetEffect MakeNoRetHard() {
+ return RetEffect(NoRetHard);
+ }
+};
+
+/// 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) : Ret(R) {}
+
+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);
+};
+
+}}}
+
+#endif
+
diff --git a/lib/ARCMigrate/CMakeLists.txt b/lib/ARCMigrate/CMakeLists.txt
index 619328ca5c..b716a20fe6 100644
--- a/lib/ARCMigrate/CMakeLists.txt
+++ b/lib/ARCMigrate/CMakeLists.txt
@@ -34,4 +34,5 @@ add_clang_library(clangARCMigrate
clangRewrite
clangSema
clangSerialization
+ clangStaticAnalyzerCheckers
)
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index 29cdb6f532..7353c8c479 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "Transforms.h"
-#include "clang/Analysis/RetainSummaryManager.h"
+#include "clang/Analysis/ObjCRetainCount.h"
#include "clang/ARCMigrate/ARCMT.h"
#include "clang/ARCMigrate/ARCMTActions.h"
#include "clang/AST/ASTConsumer.h"
@@ -35,8 +35,8 @@
#include "llvm/Support/YAMLParser.h"
using namespace clang;
-using namespace ento;
using namespace arcmt;
+using namespace ento::objc_retain;
namespace {
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 818ea16aa7..432067d981 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -24,7 +24,6 @@ add_clang_library(clangAnalysis
ProgramPoint.cpp
PseudoConstantAnalysis.cpp
ReachableCode.cpp
- RetainSummaryManager.cpp
ScanfFormatString.cpp
ThreadSafety.cpp
ThreadSafetyCommon.cpp
diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 0e0dc76baf..cff0f0a29b 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -14,13 +14,13 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "SelectorExtras.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
-#include "clang/StaticAnalyzer/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 25cd526e5c..0b2aab94da 100644
--- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -77,6 +77,7 @@ add_clang_library(clangStaticAnalyzerCheckers
PointerSubChecker.cpp
PthreadLockChecker.cpp
RetainCountChecker/RetainCountChecker.cpp
+ RetainCountChecker/RetainCountSummaries.cpp
RetainCountChecker/RetainCountDiagnostics.cpp
ReturnPointerRangeChecker.cpp
ReturnUndefChecker.cpp
diff --git a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
index 8a973bb6c1..8a5c769b6b 100644
--- a/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "SelectorExtras.h"
#include "clang/AST/Attr.h"
-#include "clang/StaticAnalyzer/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index 9d6c8314d8..a8957e1704 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -16,6 +16,7 @@
using namespace clang;
using namespace ento;
+using namespace objc_retain;
using namespace retaincountchecker;
using llvm::StrInStrNoCase;
@@ -330,19 +331,7 @@ void RetainCountChecker::checkPostStmt(const ObjCIvarRefExpr *IRE,
void RetainCountChecker::checkPostCall(const CallEvent &Call,
CheckerContext &C) const {
RetainSummaryManager &Summaries = getSummaryManager(C);
-
- // Leave null if no receiver.
- QualType ReceiverType;
- if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) {
- if (MC->isInstanceMessage()) {
- SVal ReceiverV = MC->getReceiverSVal();
- if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
- if (const RefVal *T = getRefBinding(C.getState(), Sym))
- ReceiverType = T->getType();
- }
- }
-
- const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType);
+ const RetainSummary *Summ = Summaries.getSummary(Call, C.getState());
if (C.wasInlined) {
processSummaryOfInlined(*Summ, Call, C);
@@ -1399,6 +1388,45 @@ void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State,
}
//===----------------------------------------------------------------------===//
+// Implementation of the CallEffects API.
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+namespace ento {
+namespace objc_retain {
+
+// This is a bit gross, but it allows us to populate CallEffects without
+// creating a bunch of accessors. This kind is very localized, so the
+// damage of this macro is limited.
+#define createCallEffect(D, KIND)\
+ ASTContext &Ctx = D->getASTContext();\
+ LangOptions L = Ctx.getLangOpts();\
+ RetainSummaryManager M(Ctx, L.ObjCAutoRefCount);\
+ const RetainSummary *S = M.get ## KIND ## Summary(D);\
+ CallEffects CE(S->getRetEffect());\
+ CE.Receiver = S->getReceiverEffect();\
+ unsigned N = D->param_size();\
+ for (unsigned i = 0; i < N; ++i) {\
+ CE.Args.push_back(S->getArg(i));\
+ }
+
+CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
+ createCallEffect(MD, Method);
+ return CE;
+}
+
+CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
+ createCallEffect(FD, Function);
+ return CE;
+}
+
+#undef createCallEffect
+
+} // end namespace objc_retain
+} // end namespace ento
+} // end namespace clang
+
+//===----------------------------------------------------------------------===//
// Checker registration.
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
index 6d90655d3d..9946591c4d 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
@@ -17,16 +17,17 @@
#include "../ClangSACheckers.h"
#include "../AllocationDiagnostics.h"
+#include "../SelectorExtras.h"
+#include "RetainCountSummaries.h"
#include "RetainCountDiagnostics.h"
+#include "clang/Analysis/ObjCRetainCount.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#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/StaticAnalyzer/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -45,6 +46,7 @@
#include <cstdarg>
#include <utility>
+using namespace objc_retain;
using llvm::StrInStrNoCase;
namespace clang {
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
index 8634c37c34..cbdfe3a916 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
@@ -15,7 +15,7 @@
#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
-#include "clang/Analysis/RetainSummaryManager.h"
+#include "RetainCountSummaries.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
diff --git a/lib/Analysis/RetainSummaryManager.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp
index ba2fce40c5..18813741f2 100644
--- a/lib/Analysis/RetainSummaryManager.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp
@@ -1,4 +1,4 @@
-//== RetainSummaryManager.cpp - Summaries for reference counting --*- C++ -*--//
+//== RetainCountSummaries.cpp - Checks for leaks and other issues -*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
@@ -7,21 +7,25 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines summaries implementation for retain counting, which
+// This file defines summaries implementation for RetainCountChecker, which
// implements a reference count checker for Core Foundation and Cocoa
// on (Mac OS X).
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/RetainSummaryManager.h"
+#include "RetainCountSummaries.h"
+#include "RetainCountChecker.h"
+
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ParentMap.h"
+using namespace objc_retain;
using namespace clang;
using namespace ento;
+using namespace retaincountchecker;
ArgEffects RetainSummaryManager::getArgEffects() {
ArgEffects AE = ScratchArgs;
@@ -404,7 +408,7 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
const RetainSummary *
RetainSummaryManager::getSummary(const CallEvent &Call,
- QualType ReceiverType) {
+ ProgramStateRef State) {
const RetainSummary *Summ;
switch (Call.getKind()) {
case CE_Function:
@@ -421,7 +425,7 @@ RetainSummaryManager::getSummary(const CallEvent &Call,
case CE_ObjCMessage: {
const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
if (Msg.isInstanceMessage())
- Summ = getInstanceMethodSummary(Msg, ReceiverType);
+ Summ = getInstanceMethodSummary(Msg, State);
else
Summ = getClassMethodSummary(Msg);
break;
@@ -735,15 +739,22 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
return getPersistentSummary(ResultEff, ReceiverEff, MayEscape);
}
-const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
- const ObjCMethodCall &Msg, QualType ReceiverType) {
+const RetainSummary *
+RetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg,
+ ProgramStateRef State) {
const ObjCInterfaceDecl *ReceiverClass = nullptr;
// We do better tracking of the type of the object than the core ExprEngine.
// See if we have its type in our private state.
- if (!ReceiverType.isNull())
- if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>())
- ReceiverClass = PT->getInterfaceDecl();
+ // FIXME: Eventually replace the use of state->get<RefBindings> with
+ // a generic API for reasoning about the Objective-C types of symbolic
+ // objects.
+ SVal ReceiverV = Msg.getReceiverSVal();
+ if (SymbolRef Sym = ReceiverV.getAsLocSymbol())
+ if (const RefVal *T = getRefBinding(State, Sym))
+ if (const ObjCObjectPointerType *PT =
+ T->getType()->getAs<ObjCObjectPointerType>())
+ ReceiverClass = PT->getInterfaceDecl();
// If we don't know what kind of object this is, fall back to its static type.
if (!ReceiverClass)
@@ -873,30 +884,3 @@ void RetainSummaryManager::InitializeMethodSummaries() {
"format", "colorSpace");
addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");
}
-
-CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
- ASTContext &Ctx = MD->getASTContext();
- LangOptions L = Ctx.getLangOpts();
- RetainSummaryManager M(Ctx, L.ObjCAutoRefCount);
- const RetainSummary *S = M.getMethodSummary(MD);
- CallEffects CE(S->getRetEffect());
- CE.Receiver = 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();
- LangOptions L = Ctx.getLangOpts();
- RetainSummaryManager M(Ctx, L.ObjCAutoRefCount);
- 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;
-}
diff --git a/include/clang/Analysis/RetainSummaryManager.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h
index b13dc98637..dd56a44858 100644
--- a/include/clang/Analysis/RetainSummaryManager.h
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h
@@ -1,4 +1,4 @@
-//=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
+//=== RetainCountSummaries.h - Checks for leaks and other issues -*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
@@ -7,22 +7,25 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines summaries implementation for retain counting, which
+// This file defines summaries implementation for RetainCountChecker, which
// implements a reference count checker for Core Foundation and Cocoa
// on (Mac OS X).
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_ANALYSIS_RETAINSUMMARYMANAGER
-#define LLVM_CLANG_LIB_ANALYSIS_RETAINSUMMARYMANAGER
+#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_SUMMARY_H
+#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_SUMMARY_H
+#include "../ClangSACheckers.h"
+#include "../AllocationDiagnostics.h"
+#include "../SelectorExtras.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
+#include "clang/Analysis/ObjCRetainCount.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ParentMap.h"
-#include "clang/StaticAnalyzer/Checkers/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -41,206 +44,11 @@
using namespace clang;
using namespace ento;
+using namespace objc_retain;
namespace clang {
namespace ento {
-
-/// An ArgEffect summarizes the retain count behavior on an argument or receiver
-/// to a function or method.
-enum ArgEffect {
- /// There is no effect.
- DoNothing,
-
- /// The argument is treated as if an -autorelease message had been sent to
- /// the referenced object.
- Autorelease,
-
- /// The argument is treated as if an -dealloc message had been sent to
- /// the referenced object.
- Dealloc,
-
- /// The argument has its reference count decreased by 1. This is as
- /// if CFRelease has been called on the argument.
- DecRef,
-
- /// The argument has its reference count decreased by 1. This is as
- /// if a -release message has been sent to the argument. This differs
- /// in behavior from DecRef when GC is enabled.
- DecRefMsg,
-
- /// The argument has its reference count decreased by 1 to model
- /// a transferred bridge cast under ARC.
- DecRefBridgedTransferred,
-
- /// The argument has its reference count increased by 1. This is as
- /// if a -retain message has been sent to the argument. This differs
- /// in behavior from IncRef when GC is enabled.
- IncRefMsg,
-
- /// The argument has its reference count increased by 1. This is as
- /// if CFRetain has been called on the argument.
- IncRef,
-
- /// The argument acts as if has been passed to CFMakeCollectable, which
- /// transfers the object to the Garbage Collector under GC.
- MakeCollectable,
-
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +0 value or NULL.
- UnretainedOutParameter,
-
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +1 value or NULL.
- RetainedOutParameter,
-
- /// The argument is treated as potentially escaping, meaning that
- /// even when its reference count hits 0 it should be treated as still
- /// possibly being alive as someone else *may* be holding onto the object.
- MayEscape,
-
- /// All typestate tracking of the object ceases. This is usually employed
- /// when the effect of the call is completely unknown.
- StopTracking,
-
- /// All typestate tracking of the object ceases. Unlike StopTracking,
- /// this is also enforced when the method body is inlined.
- ///
- /// In some cases, we obtain a better summary for this checker
- /// by looking at the call site than by inlining the function.
- /// Signifies that we should stop tracking the symbol even if
- /// the function is inlined.
- StopTrackingHard,
-
- /// Performs the combined functionality of DecRef and StopTrackingHard.
- ///
- /// The models the effect that the called function decrements the reference
- /// count of the argument and all typestate tracking on that argument
- /// should cease.
- DecRefAndStopTrackingHard,
-
- /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
- ///
- /// The models the effect that the called function decrements the reference
- /// count of the argument and all typestate tracking on that argument
- /// should cease.
- DecRefMsgAndStopTrackingHard
-};
-
-/// RetEffect summarizes a call's retain/release behavior with respect
-/// to its return value.
-class RetEffect {
-public:
- enum Kind {
- /// Indicates that no retain count information is tracked for
- /// the return value.
- NoRet,
- /// Indicates that the returned value is an owned (+1) symbol.
- OwnedSymbol,
- /// Indicates that the returned value is an object with retain count
- /// semantics but that it is not owned (+0). This is the default
- /// for getters, etc.
- NotOwnedSymbol,
- /// Indicates that the object is not owned and controlled by the
- /// Garbage collector.
- GCNotOwnedSymbol,
- /// Indicates that the return value is an owned object when the
- /// receiver is also a tracked object.
- OwnedWhenTrackedReceiver,
- // Treat this function as returning a non-tracked symbol even if
- // the function has been inlined. This is used where the call
- // site summary is more presise than the summary indirectly produced
- // by inlining the function
- NoRetHard
- };
-
- /// Determines the object kind of a tracked object.
- enum ObjKind {
- /// Indicates that the tracked object is a CF object. This is
- /// important between GC and non-GC code.
- CF,
- /// Indicates that the tracked object is an Objective-C object.
- ObjC,
- /// Indicates that the tracked object could be a CF or Objective-C object.
- AnyObj,
- /// Indicates that the tracked object is a generalized object.
- Generalized
- };
-
-private:
- Kind K;
- ObjKind O;
-
- RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
-
-public:
- Kind getKind() const { return K; }
-
- ObjKind getObjKind() const { return O; }
-
- bool isOwned() const {
- return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
- }
-
- bool notOwned() const {
- return K == NotOwnedSymbol;
- }
-
- bool operator==(const RetEffect &Other) const {
- return K == Other.K && O == Other.O;
- }
-
- static RetEffect MakeOwnedWhenTrackedReceiver() {
- return RetEffect(OwnedWhenTrackedReceiver, ObjC);
- }
-
- static RetEffect MakeOwned(ObjKind o) {
- return RetEffect(OwnedSymbol, o);
- }
- static RetEffect MakeNotOwned(ObjKind o) {
- return RetEffect(NotOwnedSymbol, o);
- }
- static RetEffect MakeGCNotOwned() {
- return RetEffect(GCNotOwnedSymbol, ObjC);
- }
- static RetEffect MakeNoRet() {
- return RetEffect(NoRet);
- }
- static RetEffect MakeNoRetHard() {
- return RetEffect(NoRetHard);
- }
-};
-
-/// 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) : Ret(R) {}
-
-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);
-};
+namespace retaincountchecker {
/// A key identifying a summary.
class ObjCSummaryKey {
@@ -260,10 +68,12 @@ public:
Selector getSelector() const { return S; }
};
+} // end namespace retaincountchecker
} // end namespace ento
} // end namespace clang
namespace llvm {
+using namespace retaincountchecker;
template <> struct FoldingSetTrait<ArgEffect> {
static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
@@ -306,6 +116,7 @@ template <> struct DenseMapInfo<ObjCSummaryKey> {
namespace clang {
namespace ento {
+namespace retaincountchecker {
/// ArgEffects summarizes the effects of a function/method call on all of
/// its arguments.
@@ -388,12 +199,12 @@ public:
return Args.isEmpty();
}
- ArgEffects getArgEffects() const { return Args; }
-
private:
+ ArgEffects getArgEffects() const { return Args; }
ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
friend class RetainSummaryManager;
+ friend class RetainCountChecker;
};
class ObjCSummaryCache {
@@ -588,9 +399,6 @@ class RetainSummaryManager {
addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
}
- const RetainSummary * generateSummary(const FunctionDecl *FD,
- bool &AllowAnnotations);
-
public:
RetainSummaryManager(ASTContext &ctx, bool usesARC)
: Ctx(ctx),
@@ -611,7 +419,7 @@ public:
bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
const RetainSummary *getSummary(const CallEvent &Call,
- QualType ReceiverType=QualType());
+ ProgramStateRef State = nullptr);
const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
@@ -620,9 +428,8 @@ public:
QualType RetTy,
ObjCMethodSummariesTy &CachedSummaries);
- const RetainSummary *
- getInstanceMethodSummary(const ObjCMethodCall &M,
- QualType ReceiverType);
+ const RetainSummary *getInstanceMethodSummary(const ObjCMethodCall &M,
+ ProgramStateRef State);
const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
assert(!M.isInstanceMessage());
@@ -668,6 +475,10 @@ public:
RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+private:
+ const RetainSummary * generateSummary(const FunctionDecl *FD,
+ bool &AllowAnnotations);
+
friend class RetainSummaryTemplate;
};
@@ -700,6 +511,7 @@ public:
}
};
+} // end namespace retaincountchecker
} // end namespace ento
} // end namespace clang
diff --git a/include/clang/StaticAnalyzer/Checkers/SelectorExtras.h b/lib/StaticAnalyzer/Checkers/SelectorExtras.h
index 093eea2279..b11d070c62 100644
--- a/include/clang/StaticAnalyzer/Checkers/SelectorExtras.h
+++ b/lib/StaticAnalyzer/Checkers/SelectorExtras.h
@@ -33,6 +33,13 @@ static inline void lazyInitKeywordSelector(Selector &Sel, ASTContext &Ctx,
Sel = getKeywordSelector(Ctx, IIs...);
}
+static inline void lazyInitNullarySelector(Selector &Sel, ASTContext &Ctx,
+ const char *Name) {
+ if (!Sel.isNull())
+ return;
+ Sel = GetNullarySelector(Name, Ctx);
+}
+
} // end namespace ento
} // end namespace clang
diff --git a/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
index b28e604b30..f42c78a769 100644
--- a/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp
@@ -20,7 +20,7 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
-#include "clang/StaticAnalyzer/Checkers/SelectorExtras.h"
+#include "SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"