r258886 - [analyzer] Body farm: Look for property ivar in shadowing readwrite property.
Devin Coughlin via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 26 15:58:48 PST 2016
Author: dcoughlin
Date: Tue Jan 26 17:58:48 2016
New Revision: 258886
URL: http://llvm.org/viewvc/llvm-project?rev=258886&view=rev
Log:
[analyzer] Body farm: Look for property ivar in shadowing readwrite property.
After r251874, readonly properties that are shadowed by a readwrite property
in a class extension no longer have an instance variable, which caused the body
farm to not synthesize getters. Now, if a readonly property does not have an
instance variable look for a shadowing property and try to get the instance
variable from there.
rdar://problem/24060091
Modified:
cfe/trunk/lib/Analysis/BodyFarm.cpp
cfe/trunk/test/Analysis/properties.m
Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=258886&r1=258885&r2=258886&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BodyFarm.cpp (original)
+++ cfe/trunk/lib/Analysis/BodyFarm.cpp Tue Jan 26 17:58:48 2016
@@ -383,10 +383,49 @@ Stmt *BodyFarm::getBody(const FunctionDe
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());
+ 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;
Modified: cfe/trunk/test/Analysis/properties.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/properties.m?rev=258886&r1=258885&r2=258886&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/properties.m (original)
+++ cfe/trunk/test/Analysis/properties.m Tue Jan 26 17:58:48 2016
@@ -211,6 +211,33 @@ void testConsistencyAssign(Person *p) {
clang_analyzer_eval(p.friend == origFriend); // expected-warning{{UNKNOWN}}
}
+ at interface ClassWithShadowedReadWriteProperty {
+ int _f;
+}
+ at property (readonly) int someProp;
+ at end
+
+ at interface ClassWithShadowedReadWriteProperty ()
+ at property (readwrite) int someProp;
+ at end
+
+ at implementation ClassWithShadowedReadWriteProperty
+- (void)testSynthesisForShadowedReadWriteProperties; {
+ clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}}
+
+ _f = 1;
+
+ // Read of shadowed property should not invalidate receiver.
+ (void)self.someProp;
+ clang_analyzer_eval(_f == 1); // expected-warning{{TRUE}}
+
+ _f = 2;
+ // Call to getter of shadowed property should not invalidate receiver.
+ (void)[self someProp];
+ clang_analyzer_eval(_f == 2); // expected-warning{{TRUE}}
+}
+ at end
+
#if !__has_feature(objc_arc)
void testOverrelease(Person *p, int coin) {
switch (coin) {
More information about the cfe-commits
mailing list