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&, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits