summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2013-08-14 23:41:49 +0000
committerTed Kremenek <kremenek@apple.com>2013-08-14 23:41:49 +0000
commit71c080f6252f0364eb41170dcbcc277ae4311857 (patch)
treef69ce5307476f33b9e42fccdf5a20ba6127f7949
parent243c08585b891daca95b639d8cef3d890ee5ea1e (diff)
downloadbcm5719-llvm-71c080f6252f0364eb41170dcbcc277ae4311857.tar.gz
bcm5719-llvm-71c080f6252f0364eb41170dcbcc277ae4311857.zip
[static analyzer] add a simple "CallEffects" API to query the retain count semantics of a method.
This is intended to be a simplified API, whose internals are deliberately less efficient for the purpose of a simplified interface, for use with clients that want to query the analyzer's heuristics for determining retain count semantics. There are no immediate clients, but it is intended to be used by the ObjC modernizer. llvm-svn: 188433
-rw-r--r--clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h34
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp44
2 files changed, 77 insertions, 1 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
index eed6b1f7e8c..ef45d6c3269 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -180,7 +180,39 @@ public:
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.
+ llvm::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/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index f337a903e98..1a1fa4e2e9a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -317,6 +317,16 @@ public:
return DefaultArgEffect;
}
+
+ /// Return the number of argument effects. This is O(n) in the number
+ /// of arguments.
+ unsigned getNumArgs() const {
+ unsigned N = 0;
+ for (ArgEffects::iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
+ ++N;
+ };
+ return N;
+ }
void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
Args = af.add(Args, idx, e);
@@ -3675,3 +3685,37 @@ void ento::registerRetainCountChecker(CheckerManager &Mgr) {
Mgr.registerChecker<RetainCountChecker>(Mgr.getAnalyzerOptions());
}
+//===----------------------------------------------------------------------===//
+// 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.GCOnly, L.ObjCAutoRefCount);\
+ const RetainSummary *S = M.get ## KIND ## Summary(D);\
+ CallEffects CE(S->getRetEffect());\
+ CE.Receiver = S->getReceiverEffect();\
+ unsigned N = S->getNumArgs();\
+ 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
+
+}}}
OpenPOWER on IntegriCloud