[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;