factor the code that handles "expr.field" when expr is a
pointer to an objc interface out to a method in SemaExprObjC.
This is *much* uglier than it should be due to grossness in
LookupMemberExpr :(


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100957 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index a05687e..86d6938 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Sema.h"
+#include "Lookup.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExprObjC.h"
@@ -289,6 +290,114 @@
   return Method;
 }
 
+/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
+/// objective C interface.  This is a property reference expression.
+Action::OwningExprResult Sema::
+HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+                          Expr *&BaseExpr, bool &IsArrow,
+                          DeclarationName MemberName,
+                          SourceLocation MemberLoc, SourceLocation OpLoc,
+                          CXXScopeSpec &SS, DeclPtrTy ObjCImpDecl) {
+  assert(!IsArrow && "Should only be called with '.' expressions");
+  const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
+  ObjCInterfaceDecl *IFace = IFaceT->getDecl();
+  IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+
+  // Search for a declared property first.
+  if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) {
+    // Check whether we can reference this property.
+    if (DiagnoseUseOfDecl(PD, MemberLoc))
+      return ExprError();
+    QualType ResTy = PD->getType();
+    Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+    ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
+    if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))
+      ResTy = Getter->getResultType();
+    return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
+                                                   MemberLoc, BaseExpr));
+  }
+  // Check protocols on qualified interfaces.
+  for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+       E = OPT->qual_end(); I != E; ++I)
+    if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) {
+      // Check whether we can reference this property.
+      if (DiagnoseUseOfDecl(PD, MemberLoc))
+        return ExprError();
+
+      return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+                                                     MemberLoc, BaseExpr));
+    }
+  // If that failed, look for an "implicit" property by seeing if the nullary
+  // selector is implemented.
+
+  // FIXME: The logic for looking up nullary and unary selectors should be
+  // shared with the code in ActOnInstanceMessage.
+
+  Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
+  ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
+
+  // If this reference is in an @implementation, check for 'private' methods.
+  if (!Getter)
+    Getter = IFace->lookupPrivateInstanceMethod(Sel);
+
+  // Look through local category implementations associated with the class.
+  if (!Getter)
+    Getter = IFace->getCategoryInstanceMethod(Sel);
+  if (Getter) {
+    // Check if we can reference this property.
+    if (DiagnoseUseOfDecl(Getter, MemberLoc))
+      return ExprError();
+  }
+  // If we found a getter then this may be a valid dot-reference, we
+  // will look for the matching setter, in case it is needed.
+  Selector SetterSel =
+    SelectorTable::constructSetterName(PP.getIdentifierTable(),
+                                       PP.getSelectorTable(), Member);
+  ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
+  if (!Setter) {
+    // If this reference is in an @implementation, also check for 'private'
+    // methods.
+    Setter = IFace->lookupPrivateInstanceMethod(SetterSel);
+  }
+  // Look through local category implementations associated with the class.
+  if (!Setter)
+    Setter = IFace->getCategoryInstanceMethod(SetterSel);
+
+  if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+    return ExprError();
+
+  if (Getter) {
+    QualType PType;
+    PType = Getter->getResultType();
+    return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
+                                    Setter, MemberLoc, BaseExpr));
+  }
+
+  // Attempt to correct for typos in property names.
+  LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName);
+  if (CorrectTypo(Res, 0, 0, IFace, false, OPT) &&
+      Res.getAsSingle<ObjCPropertyDecl>()) {
+    Diag(MemberLoc, diag::err_property_not_found_suggest)
+      << MemberName << QualType(OPT, 0) << Res.getLookupName()
+      << FixItHint::CreateReplacement(MemberLoc,
+                                      Res.getLookupName().getAsString());
+    ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>();
+    Diag(Property->getLocation(), diag::note_previous_decl)
+      << Property->getDeclName();
+
+    return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl);
+  }
+  Diag(MemberLoc, diag::err_property_not_found)
+    << MemberName << QualType(OPT, 0);
+  if (Setter && !Getter)
+    Diag(Setter->getLocation(), diag::note_getter_unavailable)
+      << MemberName << BaseExpr->getSourceRange();
+  return ExprError();
+
+}
+
+
+
 Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
   IdentifierInfo &receiverName,
   IdentifierInfo &propertyName,