From b0b61955a10f4289cbdee6c11ef284fad04a6a70 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Thu, 6 Dec 2018 22:07:12 +0000 Subject: [PATCH] [analyzer] Rely on os_consumes_this attribute to signify that the method call consumes a reference for "this" Differential Revision: https://reviews.llvm.org/D55158 llvm-svn: 348533 --- .../clang/StaticAnalyzer/Core/RetainSummaryManager.h | 4 ++++ clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp | 3 +++ clang/test/Analysis/osobject-retain-release.cpp | 16 ++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h b/clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h index dfcbd0c..c2e9eaa 100644 --- a/clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h @@ -369,8 +369,12 @@ public: /// This is only meaningful if the summary applies to an ObjCMessageExpr*. ArgEffect getReceiverEffect() const { return Receiver; } + /// \return the effect on the "this" receiver of the method call. ArgEffect getThisEffect() const { return This; } + /// Set the effect of the method on "this". + void setThisEffect(ArgEffect e) { This = e; } + bool isNoop() const { return Ret == RetEffect::MakeNoRet() && Receiver == DoNothing && DefaultArgEffect == MayEscape && This == DoNothing diff --git a/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp b/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp index 0e82d9a..67efa54 100644 --- a/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -759,6 +759,9 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ, QualType RetTy = FD->getReturnType(); if (Optional RetE = getRetEffectFromAnnotations(RetTy, FD)) Template->setRetEffect(*RetE); + + if (FD->hasAttr()) + Template->setThisEffect(DecRef); } void diff --git a/clang/test/Analysis/osobject-retain-release.cpp b/clang/test/Analysis/osobject-retain-release.cpp index a596d0d..cf92e2d 100644 --- a/clang/test/Analysis/osobject-retain-release.cpp +++ b/clang/test/Analysis/osobject-retain-release.cpp @@ -5,6 +5,7 @@ struct OSMetaClass; #define OS_CONSUME __attribute__((os_consumed)) #define OS_RETURNS_RETAINED __attribute__((os_returns_retained)) #define OS_RETURNS_NOT_RETAINED __attribute__((os_returns_not_retained)) +#define OS_CONSUMES_THIS __attribute__((os_consumes_this)) #define OSTypeID(type) (type::metaClass) @@ -49,6 +50,11 @@ struct OSArray : public OSObject { virtual void consumeReference(OS_CONSUME OSArray *other); + void putIntoArray(OSArray *array) OS_CONSUMES_THIS; + + template + void putIntoT(T *owner) OS_CONSUMES_THIS; + static OSArray *generateArrayHasCode() { return new OSArray; } @@ -112,6 +118,16 @@ unsigned int check_attribute_indirect_propagation(MyArray *arr) { return 0; } +void check_consumes_this(OSArray *owner) { + OSArray *arr = new OSArray; + arr->putIntoArray(owner); +} + +void check_consumes_this_with_template(OSArray *owner) { + OSArray *arr = new OSArray; + arr->putIntoT(owner); +} + void check_free_no_error() { OSArray *arr = OSArray::withCapacity(10); arr->retain(); -- 2.7.4