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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits