aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/BodyFarm.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:44:14 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:44:14 +0000
commit2b6b257f4e5503a7a2675bdb8735693db769f75c (patch)
treee85e046ae7003fe3bcc8b5454cd0fa3f7407b470 /lib/Analysis/BodyFarm.cpp
parentb4348ed0b7e90c0831b925fbee00b5f179a99796 (diff)
downloadsrc-2b6b257f4e5503a7a2675bdb8735693db769f75c.tar.gz
src-2b6b257f4e5503a7a2675bdb8735693db769f75c.zip
Vendor import of clang release_39 branch r276489:vendor/clang/clang-release_39-r276489
Notes
Notes: svn path=/vendor/clang/dist/; revision=303233 svn path=/vendor/clang/clang-release_39-r276489/; revision=303234; tag=vendor/clang/clang-release_39-r276489
Diffstat (limited to 'lib/Analysis/BodyFarm.cpp')
-rw-r--r--lib/Analysis/BodyFarm.cpp57
1 files changed, 52 insertions, 5 deletions
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index 09904369ba9c..d202a0406461 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -239,7 +239,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
SourceLocation());
// (5) Create the 'if' statement.
- IfStmt *If = new (C) IfStmt(C, SourceLocation(), nullptr, UO, CS);
+ IfStmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
+ UO, CS);
return If;
}
@@ -342,9 +343,8 @@ static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
Stmt *Else = M.makeReturn(RetVal);
/// Construct the If.
- Stmt *If =
- new (C) IfStmt(C, SourceLocation(), nullptr, Comparison, Body,
- SourceLocation(), Else);
+ Stmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,
+ Comparison, Body, SourceLocation(), Else);
return If;
}
@@ -383,10 +383,49 @@ Stmt *BodyFarm::getBody(const FunctionDecl *D) {
return Val.getValue();
}
+static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
+ const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
+
+ if (IVar)
+ return IVar;
+
+ // When a readonly property is shadowed in a class extensions with a
+ // a readwrite property, the instance variable belongs to the shadowing
+ // property rather than the shadowed property. If there is no instance
+ // variable on a readonly property, check to see whether the property is
+ // shadowed and if so try to get the instance variable from shadowing
+ // property.
+ if (!Prop->isReadOnly())
+ return nullptr;
+
+ auto *Container = cast<ObjCContainerDecl>(Prop->getDeclContext());
+ const ObjCInterfaceDecl *PrimaryInterface = nullptr;
+ if (auto *InterfaceDecl = dyn_cast<ObjCInterfaceDecl>(Container)) {
+ PrimaryInterface = InterfaceDecl;
+ } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(Container)) {
+ PrimaryInterface = CategoryDecl->getClassInterface();
+ } else if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container)) {
+ PrimaryInterface = ImplDecl->getClassInterface();
+ } else {
+ return nullptr;
+ }
+
+ // FindPropertyVisibleInPrimaryClass() looks first in class extensions, so it
+ // is guaranteed to find the shadowing property, if it exists, rather than
+ // the shadowed property.
+ auto *ShadowingProp = PrimaryInterface->FindPropertyVisibleInPrimaryClass(
+ Prop->getIdentifier(), Prop->getQueryKind());
+ if (ShadowingProp && ShadowingProp != Prop) {
+ IVar = ShadowingProp->getPropertyIvarDecl();
+ }
+
+ return IVar;
+}
+
static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
const ObjCPropertyDecl *Prop) {
// First, find the backing ivar.
- const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
+ const ObjCIvarDecl *IVar = findBackingIvar(Prop);
if (!IVar)
return nullptr;
@@ -459,6 +498,14 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
return nullptr;
// For now, we only synthesize getters.
+ // Synthesizing setters would cause false negatives in the
+ // RetainCountChecker because the method body would bind the parameter
+ // to an instance variable, causing it to escape. This would prevent
+ // warning in the following common scenario:
+ //
+ // id foo = [[NSObject alloc] init];
+ // self.foo = foo; // We should warn that foo leaks here.
+ //
if (D->param_size() != 0)
return nullptr;