[analyzer] Tighten up sanity checks on Objective-C property getter synthesis.
If there are non-trivially-copyable types /other/ than C++ records, we
won't have a synthesized copy expression, but we can't just use a simple
load/return.
Also, add comments and shore up tests, making sure to test in both ARC
and non-ARC.
llvm-svn: 199869
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index 6ec63c7..737e150 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -387,12 +387,20 @@
static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
const ObjCPropertyDecl *Prop) {
+ // First, find the backing ivar.
const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
if (!IVar)
return 0;
+
+ // Ignore weak variables, which have special behavior.
if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
return 0;
+ // 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) {
@@ -410,10 +418,18 @@
}
}
- if (IVar->getType().getCanonicalType() !=
- Prop->getType().getNonReferenceType().getCanonicalType())
+ // 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 0;
+ if (!IVar->getType()->isObjCLifetimeType() &&
+ !IVar->getType().isTriviallyCopyableType(Ctx))
return 0;
+ // Generate our body:
+ // return self->_ivar;
ASTMaker M(Ctx);
const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
@@ -431,7 +447,8 @@
return M.makeReturn(loadedIVar);
}
-Stmt *BodyFarm::getBody(const ObjCMethodDecl *D, const ObjCPropertyDecl *Prop) {
+Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
+ // We currently only know how to synthesize property accessors.
if (!D->isPropertyAccessor())
return 0;
@@ -442,11 +459,11 @@
return Val.getValue();
Val = 0;
- if (!Prop)
- Prop = D->findPropertyDecl();
+ const ObjCPropertyDecl *Prop = D->findPropertyDecl();
if (!Prop)
return 0;
+ // For now, we only synthesize getters.
if (D->param_size() != 0)
return 0;