objective-c: warn on use of property setters
backing two propeties because proprty names
match except for first letter being of different
case. // rdar://11528439, [PR12936].


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157435 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index 5e44c9b..82bf79b 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -34,6 +34,7 @@
 #include "clang/Sema/Initialization.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
 
 using namespace clang;
 using namespace sema;
@@ -232,7 +233,7 @@
                                     Expr *op);
 
     bool tryBuildGetOfReference(Expr *op, ExprResult &result);
-    bool findSetter();
+    bool findSetter(bool warn=true);
     bool findGetter();
 
     Expr *rebuildAndCaptureObject(Expr *syntacticBase);
@@ -505,7 +506,7 @@
 /// reference.
 ///
 /// \return true if a setter was found, in which case Setter 
-bool ObjCPropertyOpBuilder::findSetter() {
+bool ObjCPropertyOpBuilder::findSetter(bool warn) {
   // For implicit properties, just trust the lookup we already did.
   if (RefExpr->isImplicitProperty()) {
     if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
@@ -531,6 +532,23 @@
   // Do a normal method lookup first.
   if (ObjCMethodDecl *setter =
         LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
+    if (setter->isSynthesized() && warn)
+      if (const ObjCInterfaceDecl *IFace =
+          dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
+        const StringRef thisPropertyName(prop->getName());
+        char front = thisPropertyName.front();
+        front = islower(front) ? toupper(front) : tolower(front);
+        SmallString<100> PropertyName = thisPropertyName;
+        PropertyName[0] = front;
+        IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName);
+        if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember))
+          if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
+            S.Diag(RefExpr->getExprLoc(), diag::warn_property_setter_ambiguous_use)
+              << prop->getName() << prop1->getName() << setter->getSelector();
+            S.Diag(prop->getLocation(), diag::note_property_declare);
+            S.Diag(prop1->getLocation(), diag::note_property_declare);
+          }
+      }
     Setter = setter;
     return true;
   }
@@ -603,7 +621,7 @@
 ///   value being set as the value of the property operation.
 ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
                                            bool captureSetValueAsResult) {
-  bool hasSetter = findSetter();
+  bool hasSetter = findSetter(false);
   assert(hasSetter); (void) hasSetter;
 
   if (SyntacticRefExpr)