[index/AST] Add references for ObjC getter=/setter= property attributes and related property getter/setter role fixes

This enhances the AST to keep track of locations of the names in those ObjC property attributes, and reports them for indexing.

Patch by Nathan Hawes!
https://reviews.llvm.org/D30907

llvm-svn: 297972
diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp
index 7681de7..7f09290 100644
--- a/clang/lib/Index/IndexBody.cpp
+++ b/clang/lib/Index/IndexBody.cpp
@@ -22,6 +22,10 @@
   SmallVector<Stmt*, 16> StmtStack;
 
   typedef RecursiveASTVisitor<BodyIndexer> base;
+
+  Stmt *getParentStmt() const {
+    return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
+  }
 public:
   BodyIndexer(IndexingContext &indexCtx,
               const NamedDecl *Parent, const DeclContext *DC)
@@ -178,7 +182,8 @@
       SymbolRoleSet Roles{};
       SmallVector<SymbolRelation, 2> Relations;
       addCallRole(Roles, Relations);
-      if (E->isImplicit())
+      Stmt *Containing = getParentStmt();
+      if (E->isImplicit() || (Containing && isa<PseudoObjectExpr>(Containing)))
         Roles |= (unsigned)SymbolRole::Implicit;
 
       if (isDynamic(E)) {
@@ -194,9 +199,12 @@
   }
 
   bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
-    if (E->isExplicitProperty())
+    if (E->isExplicitProperty()) {
+      SmallVector<SymbolRelation, 2> Relations;
+      SymbolRoleSet Roles = getRolesForRef(E, Relations);
       return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
-                                      Parent, ParentDC, SymbolRoleSet(), {}, E);
+                                      Parent, ParentDC, Roles, Relations, E);
+    }
 
     // No need to do a handleReference for the objc method, because there will
     // be a message expr as part of PseudoObjectExpr.
diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp
index 4c5a87b..581e3a2 100644
--- a/clang/lib/Index/IndexDecl.cpp
+++ b/clang/lib/Index/IndexDecl.cpp
@@ -98,9 +98,28 @@
     if (MethodLoc.isInvalid())
       MethodLoc = D->getLocation();
 
+    SourceLocation AttrLoc;
+
+    // check for (getter=/setter=)
+    if (AssociatedProp) {
+      bool isGetter = !D->param_size();
+      AttrLoc = isGetter ?
+        AssociatedProp->getGetterNameLoc():
+        AssociatedProp->getSetterNameLoc();
+    }
+
     SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
-    if (D->isImplicit())
-      Roles |= (SymbolRoleSet)SymbolRole::Implicit;
+    if (D->isImplicit()) {
+      if (AttrLoc.isValid()) {
+        MethodLoc = AttrLoc;
+      } else {
+        Roles |= (SymbolRoleSet)SymbolRole::Implicit;
+      }
+    } else if (AttrLoc.isValid()) {
+      IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
+                               D->getDeclContext(), 0);
+    }
+
     if (!IndexCtx.handleDecl(D, MethodLoc, Roles, Relations))
       return false;
     IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);