[clang-tools-extra] b1fbc05 - [clangd] Support "usedAsMutableReference" in member initializations

Nathan Ridge via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 8 20:16:37 PDT 2022


Author: Christian Kandeler
Date: 2022-07-08T23:16:20-04:00
New Revision: b1fbc0519c5224de44b2711f8a813b24d767dd3e

URL: https://github.com/llvm/llvm-project/commit/b1fbc0519c5224de44b2711f8a813b24d767dd3e
DIFF: https://github.com/llvm/llvm-project/commit/b1fbc0519c5224de44b2711f8a813b24d767dd3e.diff

LOG: [clangd] Support "usedAsMutableReference" in member initializations

That is, mark constructor parameters being used to initialize
non-const reference members.

Reviewed By: nridge

Differential Revision: https://reviews.llvm.org/D128977

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index 5e0e3b2cc7dc..63d01deb3370 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -523,6 +523,8 @@ llvm::Optional<HighlightingModifier> scopeModifier(const Type *T) {
 /// e.g. highlights dependent names and 'auto' as the underlying type.
 class CollectExtraHighlightings
     : public RecursiveASTVisitor<CollectExtraHighlightings> {
+  using Base = RecursiveASTVisitor<CollectExtraHighlightings>;
+
 public:
   CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}
 
@@ -533,6 +535,13 @@ class CollectExtraHighlightings
     return true;
   }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
+    if (Init->isMemberInitializer())
+      if (auto *Member = Init->getMember())
+        highlightMutableReferenceArgument(Member->getType(), Init->getInit());
+    return Base::TraverseConstructorInitializer(Init);
+  }
+
   bool VisitCallExpr(CallExpr *E) {
     // Highlighting parameters passed by non-const reference does not really
     // make sense for literals...
@@ -542,8 +551,8 @@ class CollectExtraHighlightings
     // FIXME: consider highlighting parameters of some other overloaded
     // operators as well
     llvm::ArrayRef<const Expr *> Args = {E->getArgs(), E->getNumArgs()};
-    if (const auto callOp = dyn_cast<CXXOperatorCallExpr>(E)) {
-      switch (callOp->getOperator()) {
+    if (auto *CallOp = dyn_cast<CXXOperatorCallExpr>(E)) {
+      switch (CallOp->getOperator()) {
       case OO_Call:
       case OO_Subscript:
         Args = Args.drop_front(); // Drop object parameter
@@ -559,6 +568,33 @@ class CollectExtraHighlightings
     return true;
   }
 
+  void highlightMutableReferenceArgument(QualType T, const Expr *Arg) {
+    if (!Arg)
+      return;
+
+    // Is this parameter passed by non-const reference?
+    // FIXME The condition T->idDependentType() could be relaxed a bit,
+    // e.g. std::vector<T>& is dependent but we would want to highlight it
+    if (!T->isLValueReferenceType() ||
+        T.getNonReferenceType().isConstQualified() || T->isDependentType()) {
+      return;
+    }
+
+    llvm::Optional<SourceLocation> Location;
+
+    // FIXME Add "unwrapping" for ArraySubscriptExpr and UnaryOperator,
+    //  e.g. highlight `a` in `a[i]`
+    // FIXME Handle dependent expression types
+    if (auto *DR = dyn_cast<DeclRefExpr>(Arg))
+      Location = DR->getLocation();
+    else if (auto *M = dyn_cast<MemberExpr>(Arg))
+      Location = M->getMemberLoc();
+
+    if (Location)
+      H.addExtraModifier(*Location,
+                         HighlightingModifier::UsedAsMutableReference);
+  }
+
   void
   highlightMutableReferenceArguments(const FunctionDecl *FD,
                                      llvm::ArrayRef<const Expr *const> Args) {
@@ -571,31 +607,7 @@ class CollectExtraHighlightings
       // highlighting modifier to the corresponding expression
       for (size_t I = 0;
            I < std::min(size_t(ProtoType->getNumParams()), Args.size()); ++I) {
-        auto T = ProtoType->getParamType(I);
-
-        // Is this parameter passed by non-const reference?
-        // FIXME The condition !T->idDependentType() could be relaxed a bit,
-        // e.g. std::vector<T>& is dependent but we would want to highlight it
-        if (T->isLValueReferenceType() &&
-            !T.getNonReferenceType().isConstQualified() &&
-            !T->isDependentType()) {
-          if (auto *Arg = Args[I]) {
-            llvm::Optional<SourceLocation> Location;
-
-            // FIXME Add "unwrapping" for ArraySubscriptExpr and UnaryOperator,
-            //  e.g. highlight `a` in `a[i]`
-            // FIXME Handle dependent expression types
-            if (auto *DR = dyn_cast<DeclRefExpr>(Arg)) {
-              Location = DR->getLocation();
-            } else if (auto *M = dyn_cast<MemberExpr>(Arg)) {
-              Location = M->getMemberLoc();
-            }
-
-            if (Location)
-              H.addExtraModifier(*Location,
-                                 HighlightingModifier::UsedAsMutableReference);
-          }
-        }
+        highlightMutableReferenceArgument(ProtoType->getParamType(I), Args[I]);
       }
     }
   }

diff  --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
index a40a0f92e4a6..384840c93f66 100644
--- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -745,6 +745,23 @@ sizeof...($TemplateParameter[[Elements]]);
             int &operator[](int &);
             int operator[](int) const;
         };
+        struct $Class_decl[[ClassWithStaticMember]] {
+            static inline int $StaticField_decl_static[[j]] = 0;
+        };
+        struct $Class_decl[[ClassWithRefMembers]] {
+          $Class_decl[[ClassWithRefMembers]](int $Parameter_decl[[i]])
+            : $Field[[i1]]($Parameter[[i]]),
+              $Field_readonly[[i2]]($Parameter[[i]]),
+              $Field[[i3]]($Parameter_usedAsMutableReference[[i]]),
+              $Field_readonly[[i4]]($Class[[ClassWithStaticMember]]::$StaticField_static[[j]]),
+              $Field[[i5]]($Class[[ClassWithStaticMember]]::$StaticField_static_usedAsMutableReference[[j]])
+          {}
+          int $Field_decl[[i1]];
+          const int &$Field_decl_readonly[[i2]];
+          int &$Field_decl[[i3]];
+          const int &$Field_decl_readonly[[i4]];
+          int &$Field_decl[[i5]];
+        };
         void $Function_decl[[fun]](int, const int,
                                    int*, const int*,
                                    int&, const int&,


        


More information about the cfe-commits mailing list