diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:44:14 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:44:14 +0000 |
commit | 2b6b257f4e5503a7a2675bdb8735693db769f75c (patch) | |
tree | e85e046ae7003fe3bcc8b5454cd0fa3f7407b470 /lib/Analysis/BodyFarm.cpp | |
parent | b4348ed0b7e90c0831b925fbee00b5f179a99796 (diff) | |
download | src-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.cpp | 57 |
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; |