t-troebst updated this revision to Diff 518641.
t-troebst added a comment.

Add best effort attempt to get const-ness for dependent member expressions.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D148284/new/

https://reviews.llvm.org/D148284

Files:
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -1154,6 +1154,109 @@
     checkHighlightings(Test, {}, ScopeModifierMask);
 }
 
+TEST(SemanticHighlighting, MemberReadonly) {
+  const char *TestCases[] = {
+      R"cpp(
+        struct $Class[[A]] {
+          int $Field[[x]];
+          const int $Field_readonly[[y]];
+          mutable int $Field[[z]];
+        };
+        void $Function[[foo]](){
+          $Class[[A]] $LocalVariable[[a]]{};
+          $LocalVariable[[a]].$Field[[x]];
+          $LocalVariable[[a]].$Field_readonly[[y]];
+          $LocalVariable[[a]].$Field[[z]];
+          const $Class[[A]] $LocalVariable_readonly[[b]]{};
+          $LocalVariable_readonly[[b]].$Field_readonly[[x]];
+          $LocalVariable_readonly[[b]].$Field_readonly[[y]];
+          $LocalVariable_readonly[[b]].$Field[[z]];
+        }
+      )cpp",
+      R"cpp(
+        struct $Class[[A]] {
+          int $Field[[x]];
+          const int $Field_readonly[[y]];
+          mutable int $Field[[z]];
+        };
+        void $Function[[foo]](){
+          $Class[[A]] *$LocalVariable[[a]] = $Operator[[new]] $Class[[A]]{};
+          $LocalVariable[[a]]->$Field[[x]];
+          $LocalVariable[[a]]->$Field_readonly[[y]];
+          $LocalVariable[[a]]->$Field[[z]];
+          const $Class[[A]] *$LocalVariable_readonly[[b]] = $Operator[[new]] $Class[[A]]{};
+          $LocalVariable_readonly[[b]]->$Field_readonly[[x]];
+          $LocalVariable_readonly[[b]]->$Field_readonly[[y]];
+          $LocalVariable_readonly[[b]]->$Field[[z]];
+        }
+      )cpp",
+      R"cpp(
+        struct $Class[[A]] {
+          int $Field[[x]];
+          const int $Field_readonly[[y]];
+          mutable int $Field[[z]];
+          void $Method_readonly[[foo]]() const {
+            $Field_readonly[[x]];
+            $Field_readonly[[y]];
+            $Field[[z]];
+          }
+          void $Method[[bar]]() {
+            $Field[[x]];
+            $Field_readonly[[y]];
+            $Field[[z]];
+          }
+        };
+      )cpp",
+      R"cpp(
+        struct $Class[[A]] {
+          int $Field[[x]];
+          const int $Field_readonly[[y]];
+          mutable int $Field[[z]];
+          void $Method_readonly[[foo]]() const {
+            this->$Field_readonly[[x]];
+            this->$Field_readonly[[y]];
+            this->$Field[[z]];
+          }
+          void $Method[[bar]]() {
+            this->$Field[[x]];
+            this->$Field_readonly[[y]];
+            this->$Field[[z]];
+          }
+        };
+      )cpp",
+      R"cpp(
+        struct $Class[[A]] {
+          void $Method_readonly[[foo]]() const {}
+          void $Method[[foo]]() {}
+          void $Method_readonly[[test]]() const {
+            $Method_readonly[[foo]]();
+          }
+          void $Method[[test]]() {
+            $Method[[foo]]();
+          }
+        };
+      )cpp",
+      R"cpp(
+        template $Bracket[[<]]typename $TemplateParameter[[T]]$Bracket[[>]]
+        void $Function[[foo]]($TemplateParameter[[T]] $Parameter[[x]], const $TemplateParameter[[T]] $Parameter_readonly[[y]]) {
+          $Parameter[[x]].$Unknown[[a]];
+          $Parameter_readonly[[y]].$Unknown_readonly[[b]];
+        }
+      )cpp",
+      R"cpp(
+        template $Bracket[[<]]typename $TemplateParameter[[T]]$Bracket[[>]]
+        void $Function[[foo]]($TemplateParameter[[T]]* $Parameter[[x]], const $TemplateParameter[[T]]* $Parameter_readonly[[y]], $TemplateParameter[[T]]* const $Parameter_readonly[[z]]) {
+          $Parameter[[x]]->$Unknown[[a]];
+          $Parameter_readonly[[y]]->$Unknown_readonly[[b]];
+          $Parameter_readonly[[z]]->$Unknown[[c]];
+        }
+      )cpp",
+  };
+
+  for (const char *Test : TestCases)
+    checkHighlightings(Test, {}, 1 << unsigned(HighlightingModifier::Readonly));
+}
+
 // Ranges are highlighted as variables, unless highlighted as $Function etc.
 std::vector<HighlightingToken> tokens(llvm::StringRef MarkedText) {
   Annotations A(MarkedText);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -670,8 +670,11 @@
     H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
     return true;
   }
+
   bool VisitMemberExpr(MemberExpr *E) {
     H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
+    if (isConst(E->getType()))
+      H.addExtraModifier(E->getMemberLoc(), HighlightingModifier::Readonly);
     return true;
   }
 
@@ -1003,9 +1006,19 @@
   }
 
   bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
-    H.addToken(E->getMemberNameInfo().getLoc(), HighlightingKind::Unknown)
-        .addModifier(HighlightingModifier::DependentName)
-        .addModifier(HighlightingModifier::ClassScope);
+    auto &Tok =
+        H.addToken(E->getMemberNameInfo().getLoc(), HighlightingKind::Unknown)
+            .addModifier(HighlightingModifier::DependentName)
+            .addModifier(HighlightingModifier::ClassScope);
+
+    // Best effort attempt to get const-ness for dependent member expressions.
+    // Note: this can yield false-positives if the member is mutable but this
+    // should be rare in dependent contexts.
+    const auto BaseType = E->getBaseType();
+    if ((E->isArrow() && BaseType->getPointeeType().isConstQualified()) ||
+        (!E->isArrow() && BaseType.isConstQualified()))
+      Tok.addModifier(HighlightingModifier::Readonly);
+
     H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
     return true;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to