From 9ae66a47586ba3dcc68f303bc4dfc67c02952848 Mon Sep 17 00:00:00 2001
From: Jordan Rose <jordan_rose@apple.com>
Date: Tue, 14 Jan 2014 17:29:06 +0000
Subject: [PATCH] [analyzer] Use synthesized ASTs for property getters when
 available.

This allows the analyzer to handle properties with C++ class type,
finishing up the FIXME from r198953.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199226 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Analysis/BodyFarm.cpp   | 24 ++++++++++++++++++------
 test/Analysis/properties.mm | 12 ++++++------
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index a6567ade52f..373f5d1ffa7 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -393,16 +393,28 @@ static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
     return 0;
   if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
     return 0;
+
+  const ObjCImplementationDecl *ImplDecl =
+    IVar->getContainingInterface()->getImplementation();
+  if (ImplDecl) {
+    typedef ObjCImplementationDecl::propimpl_iterator propimpl_iterator;
+    for (propimpl_iterator I = ImplDecl->propimpl_begin(),
+                           E = ImplDecl->propimpl_end();
+         I != E; ++I) {
+      if (I->getPropertyDecl() != Prop)
+        continue;
+
+      if (I->getGetterCXXConstructor()) {
+        ASTMaker M(Ctx);
+        return M.makeReturn(I->getGetterCXXConstructor());
+      }
+    }
+  }
+
   if (IVar->getType().getCanonicalType() !=
       Prop->getType().getNonReferenceType().getCanonicalType())
     return 0;
 
-  // C++ records require copy constructors, so we can't just synthesize an AST.
-  // FIXME: Use ObjCPropertyImplDecl's already-synthesized AST. Currently it's
-  // not in a form the analyzer can use.
-  if (Prop->getType()->getAsCXXRecordDecl())
-    return 0;
-
   ASTMaker M(Ctx);
 
   const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
diff --git a/test/Analysis/properties.mm b/test/Analysis/properties.mm
index dd44219856f..57aacd4f9d2 100644
--- a/test/Analysis/properties.mm
+++ b/test/Analysis/properties.mm
@@ -42,21 +42,21 @@ struct IntWrapperStruct {
 @end
 
 void testConsistencyStruct(StructWrapper *w) {
-  clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{UNKNOWN}}
+  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{{UNKNOWN}}
+  clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}}
 }
 
 
 class CustomCopy {
 public:
   CustomCopy() : value(0) {}
-  CustomCopy(const CustomCopy &other) {
-    clang_analyzer_checkInlined(false);
+  CustomCopy(const CustomCopy &other) : value(other.value) {
+    clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
   }
   int value;
 };
@@ -70,11 +70,11 @@ public:
 @end
 
 void testConsistencyCustomCopy(CustomCopyWrapper *w) {
-  clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{UNKNOWN}}
+  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{{UNKNOWN}}
+  clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}}
 }
-- 
GitLab