sammccall created this revision.
sammccall added reviewers: ilya-biryukov, dgoldman.
Herald added subscribers: cfe-commits, usaxena95, kadircet, jfb, arphaman, 
jkorous, MaskRay.
Herald added a project: clang.
sammccall added a parent revision: D72494: [clangd] Fix targetDecl() on certain 
usage of ObjC properties..
sammccall removed a parent revision: D72494: [clangd] Fix targetDecl() on 
certain usage of ObjC properties..
sammccall marked an inline comment as done.
sammccall added inline comments.


================
Comment at: clang-tools-extra/clangd/unittests/FindTargetTests.cpp:570
     auto AST = TU.build();
+    EXPECT_THAT(AST.getDiagnostics(), ::testing::IsEmpty()) << Code;
 
----------------
For consistency with the targetDecl() tests in this file, and because I had an 
error in the testcase that threw me for a loop. I'll try to find a better 
solution project-wide though.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72508

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp

Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -511,8 +511,7 @@
       [[f.x]].y = 0;
     }
   )cpp";
-  EXPECT_DECLS("OpaqueValueExpr",
-               "@property(atomic, retain, readwrite) I *x");
+  EXPECT_DECLS("OpaqueValueExpr", "@property(atomic, retain, readwrite) I *x");
 
   Code = R"cpp(
     @protocol Foo
@@ -565,8 +564,10 @@
     // parsing.
     TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
     TU.ExtraArgs.push_back("-std=c++17");
+    TU.ExtraArgs.push_back("-xobjective-c++");
 
     auto AST = TU.build();
+    EXPECT_THAT(AST.getDiagnostics(), ::testing::IsEmpty()) << Code;
 
     auto *TestDecl = &findDecl(AST, "foo");
     if (auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl))
@@ -664,7 +665,7 @@
          void foo() {
            $0^Struct $1^x;
            $2^Typedef $3^y;
-           static_cast<$4^Struct*>(0);
+           (void) static_cast<$4^Struct*>(0);
          }
        )cpp",
         "0: targets = {Struct}\n"
@@ -675,10 +676,10 @@
        // Name qualifiers.
        {R"cpp(
          namespace a { namespace b { struct S { typedef int type; }; } }
-         void foo() {
+         int foo() {
            $0^a::$1^b::$2^S $3^x;
            using namespace $4^a::$5^b;
-           $6^S::$7^type $8^y;
+           return $6^S::$7^type(5);
          }
         )cpp",
         "0: targets = {a}\n"
@@ -688,8 +689,7 @@
         "4: targets = {a}\n"
         "5: targets = {a::b}, qualifier = 'a::'\n"
         "6: targets = {a::b::S}\n"
-        "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
-        "8: targets = {y}, decl\n"},
+        "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"},
        // Simple templates.
        {R"cpp(
           template <class T> struct vector { using value_type = T; };
@@ -719,7 +719,7 @@
         "3: targets = {vb}, decl\n"},
        // MemberExpr should know their using declaration.
        {R"cpp(
-            struct X { void func(int); }
+            struct X { void func(int); };
             struct Y : X {
               using X::func;
             };
@@ -744,8 +744,8 @@
             #define FOO a
             #define BAR b
 
-            void foo(int a, int b) {
-              $0^FOO+$1^BAR;
+            int foo(int a, int b) {
+              return $0^FOO+$1^BAR;
             }
         )cpp",
         "0: targets = {a}\n"
@@ -825,7 +825,7 @@
             void foo() {
               $0^TT<int> $1^x;
               $2^foo<$3^TT>();
-              $4^foo<$5^vector>()
+              $4^foo<$5^vector>();
               $6^foo<$7^TP...>();
             }
         )cpp",
@@ -892,7 +892,7 @@
                };
                // delegating initializer
                class $10^Foo {
-                 $11^Foo(int);
+                 $11^Foo(int) {}
                  $12^Foo(): $13^Foo(111) {}
                };
              }
@@ -925,7 +925,7 @@
        // Namespace aliases should be handled properly.
        {
            R"cpp(
-                namespace ns { struct Type {} }
+                namespace ns { struct Type {}; }
                 namespace alias = ns;
                 namespace rec_alias = alias;
 
@@ -966,7 +966,21 @@
               }
             )cpp",
            "0: targets = {Test}\n"
-           "1: targets = {a}, decl\n"}};
+           "1: targets = {a}, decl\n"},
+       {
+           R"cpp(
+            @interface I {}
+            @property(retain) I* x;
+            @property(retain) I* y;
+            @end
+            I *f;
+            void foo() {
+              $0^f.$1^x.$2^y = 0;
+            }
+          )cpp",
+           "0: targets = {f}\n"
+           "1: targets = {I::x}\n"
+           "2: targets = {I::y}\n"}};
 
   for (const auto &C : Cases) {
     llvm::StringRef ExpectedCode = C.first;
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -585,7 +585,7 @@
 
 llvm::SmallVector<ReferenceLoc, 2> refInExpr(const Expr *E) {
   struct Visitor : ConstStmtVisitor<Visitor> {
-    // FIXME: handle more complicated cases, e.g. ObjC, designated initializers.
+    // FIXME: handle more complicated cases: more ObjC, designated initializers.
     llvm::SmallVector<ReferenceLoc, 2> Refs;
 
     void VisitDeclRefExpr(const DeclRefExpr *E) {
@@ -616,6 +616,14 @@
                                   /*IsDecl=*/false,
                                   {E->getPack()}});
     }
+
+    void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) {
+      Refs.push_back(ReferenceLoc{
+          NestedNameSpecifierLoc(), E->getLocation(),
+          /*IsDecl=*/false,
+          // Select the getter, setter, or @property depending on the call.
+          explicitReferenceTargets(DynTypedNode::create(*E), {})});
+    }
   };
 
   Visitor V;
@@ -729,6 +737,19 @@
     return true;
   }
 
+  bool TraverseOpaqueValueExpr(OpaqueValueExpr *OVE) {
+    visitNode(DynTypedNode::create(*OVE));
+    // Not clear why the source expression is skipped by default...
+    return RecursiveASTVisitor::TraverseStmt(OVE->getSourceExpr());
+  }
+
+  bool TraversePseudoObjectExpr(PseudoObjectExpr *POE) {
+    visitNode(DynTypedNode::create(*POE));
+    // Traverse only the syntactic form to find the *written* references.
+    // (The semantic form also contains lots of duplication)
+    return RecursiveASTVisitor::TraverseStmt(POE->getSyntacticForm());
+  }
+
   // We re-define Traverse*, since there's no corresponding Visit*.
   // TemplateArgumentLoc is the only way to get locations for references to
   // template template parameters.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to