vsavchenko created this revision.
vsavchenko added reviewers: NoQ, xazax.hun, steakhal, ASDenysPetrov.
Herald added subscribers: Charusso, dkrupp, donat.nagy, Szelethus,
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, kristof.beyls.
vsavchenko requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
When property is declared in a superclass (or in a protocol),
it still can be of CXXRecord type and Sema could've already
generated a body for us. This patch joins two branches and
two ways of acquiring IVar in order to reuse the existing code.
And prevent us from generating l-value to r-value casts for
C++ types.
rdar://67416721
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D99194
Files:
clang/lib/Analysis/BodyFarm.cpp
clang/test/Analysis/properties.mm
Index: clang/test/Analysis/properties.mm
===================================================================
--- clang/test/Analysis/properties.mm
+++ clang/test/Analysis/properties.mm
@@ -77,3 +77,23 @@
clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}}
}
+
+@protocol NoDirectPropertyDecl
+@property IntWrapperStruct inner;
+@end
+@interface NoDirectPropertyDecl <NoDirectPropertyDecl>
+@end
+@implementation NoDirectPropertyDecl
+@synthesize inner;
+@end
+
+// rdar://67416721
+void testNoDirectPropertyDecl(NoDirectPropertyDecl *w) {
+ clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}}
+
+ int origValue = w.inner.value;
+ if (origValue != 42)
+ return;
+
+ clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}}
+}
Index: clang/lib/Analysis/BodyFarm.cpp
===================================================================
--- clang/lib/Analysis/BodyFarm.cpp
+++ clang/lib/Analysis/BodyFarm.cpp
@@ -742,8 +742,9 @@
static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
const ObjCMethodDecl *MD) {
- // First, find the backing ivar.
+ // First, find the backing ivar.
const ObjCIvarDecl *IVar = nullptr;
+ const ObjCPropertyDecl *Prop = nullptr;
// Property accessor stubs sometimes do not correspond to any property decl
// in the current interface (but in a superclass). They still have a
@@ -751,54 +752,56 @@
if (MD->isSynthesizedAccessorStub()) {
const ObjCInterfaceDecl *IntD = MD->getClassInterface();
const ObjCImplementationDecl *ImpD = IntD->getImplementation();
- for (const auto *PI: ImpD->property_impls()) {
- if (const ObjCPropertyDecl *P = PI->getPropertyDecl()) {
- if (P->getGetterName() == MD->getSelector())
- IVar = P->getPropertyIvarDecl();
+ for (const auto *PI : ImpD->property_impls()) {
+ if (PI->getPropertyDecl()) {
+ Prop = PI->getPropertyDecl();
+ if (Prop->getGetterName() == MD->getSelector())
+ IVar = Prop->getPropertyIvarDecl();
}
}
}
if (!IVar) {
- const ObjCPropertyDecl *Prop = MD->findPropertyDecl();
+ Prop = MD->findPropertyDecl();
IVar = findBackingIvar(Prop);
- if (!IVar)
- return nullptr;
+ }
- // Ignore weak variables, which have special behavior.
- if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
- return nullptr;
+ if (!IVar || !Prop)
+ return nullptr;
- // Look to see if Sema has synthesized a body for us. This happens in
- // Objective-C++ because the return value may be a C++ class type with a
- // non-trivial copy constructor. We can only do this if we can find the
- // @synthesize for this property, though (or if we know it's been auto-
- // synthesized).
- const ObjCImplementationDecl *ImplDecl =
+ // Ignore weak variables, which have special behavior.
+ if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
+ return nullptr;
+
+ // Look to see if Sema has synthesized a body for us. This happens in
+ // Objective-C++ because the return value may be a C++ class type with a
+ // non-trivial copy constructor. We can only do this if we can find the
+ // @synthesize for this property, though (or if we know it's been auto-
+ // synthesized).
+ const ObjCImplementationDecl *ImplDecl =
IVar->getContainingInterface()->getImplementation();
- if (ImplDecl) {
- for (const auto *I : ImplDecl->property_impls()) {
- if (I->getPropertyDecl() != Prop)
- continue;
-
- if (I->getGetterCXXConstructor()) {
- ASTMaker M(Ctx);
- return M.makeReturn(I->getGetterCXXConstructor());
- }
+ if (ImplDecl) {
+ for (const auto *I : ImplDecl->property_impls()) {
+ if (I->getPropertyDecl() != Prop)
+ continue;
+
+ if (I->getGetterCXXConstructor()) {
+ ASTMaker M(Ctx);
+ return M.makeReturn(I->getGetterCXXConstructor());
}
}
-
- // Sanity check that the property is the same type as the ivar, or a
- // reference to it, and that it is either an object pointer or trivially
- // copyable.
- if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
- Prop->getType().getNonReferenceType()))
- return nullptr;
- if (!IVar->getType()->isObjCLifetimeType() &&
- !IVar->getType().isTriviallyCopyableType(Ctx))
- return nullptr;
}
+ // Sanity check that the property is the same type as the ivar, or a
+ // reference to it, and that it is either an object pointer or trivially
+ // copyable.
+ if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
+ Prop->getType().getNonReferenceType()))
+ return nullptr;
+ if (!IVar->getType()->isObjCLifetimeType() &&
+ !IVar->getType().isTriviallyCopyableType(Ctx))
+ return nullptr;
+
// Generate our body:
// return self->_ivar;
ASTMaker M(Ctx);
@@ -807,11 +810,8 @@
if (!selfVar)
return nullptr;
- Expr *loadedIVar =
- M.makeObjCIvarRef(
- M.makeLvalueToRvalue(
- M.makeDeclRefExpr(selfVar),
- selfVar->getType()),
+ Expr *loadedIVar = M.makeObjCIvarRef(
+ M.makeLvalueToRvalue(M.makeDeclRefExpr(selfVar), selfVar->getType()),
IVar);
if (!MD->getReturnType()->isReferenceType())
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits