https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/71366
>From 808c141c34218dd542b00149216adc061567dd31 Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Mon, 6 Nov 2023 16:50:02 +0800 Subject: [PATCH 1/4] [clangd] Don't show inlay hints for PseudoObjectExprs in C++ This closes https://github.com/clangd/clangd/issues/1813. PseudoObjectExprs in C++ are currently not very interesting but probably mess up inlay hints. --- clang-tools-extra/clangd/InlayHints.cpp | 13 ++++++++++ .../clangd/unittests/InlayHintTests.cpp | 24 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 3da047f954213856..867c70e5dbc80c65 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -589,6 +589,19 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { return true; } + bool dataTraverseStmtPre(Stmt *S) { + // Do not show inlay hints for PseudoObjectExprs. They're never + // genuine user codes in C++. + // + // For example, __builtin_dump_struct would expand to a PseudoObjectExpr + // that includes a couple of calls to a printf function. Printing parameter + // names for that anyway would end up with duplicate parameter names (which, + // however, got de-duplicated after visiting) for the printf function. + if (AST.getLangOpts().CPlusPlus && isa<PseudoObjectExpr>(S)) + return false; + return true; + } + bool VisitCallExpr(CallExpr *E) { if (!Cfg.InlayHints.Parameters) return true; diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index 20c1cdd985dbc017..2b6c27b17b537a96 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -1724,6 +1724,30 @@ TEST(InlayHints, RestrictRange) { ElementsAre(labelIs(": int"), labelIs(": char"))); } +TEST(ParameterHints, PseudoObjectExpr) { + Annotations Code(R"cpp( + struct S { + __declspec(property(get=GetX, put=PutX)) int x[]; + int GetX(int y, int z) { return 42 + y; } + void PutX(int y) { x = y; } // Not `x = y: y` + }; + + int printf(const char *Format, ...); + + int main() { + S s; + __builtin_dump_struct(&s, printf); // Not `Format: __builtin_dump_struct()` + printf($Param[["Hello, %d"]], 42); // Normal calls are not affected. + return s.x[1][2]; // Not `x[y: 1][z: 2]` + } + )cpp"); + auto TU = TestTU::withCode(Code.code()); + TU.ExtraArgs.push_back("-fms-extensions"); + auto AST = TU.build(); + EXPECT_THAT(inlayHints(AST, std::nullopt), + ElementsAre(HintMatcher(ExpectedHint{"Format: ", "Param"}, Code))); +} + TEST(ParameterHints, ArgPacksAndConstructors) { assertParameterHints( R"cpp( >From f15e35f67e23e742536ca2fe7229f5b6cba8f6b8 Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Mon, 6 Nov 2023 17:32:50 +0800 Subject: [PATCH 2/4] Don't make the patch C++-specific --- clang-tools-extra/clangd/InlayHints.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 867c70e5dbc80c65..1b54b570c1c5d4fc 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -591,13 +591,13 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { bool dataTraverseStmtPre(Stmt *S) { // Do not show inlay hints for PseudoObjectExprs. They're never - // genuine user codes in C++. + // genuine user codes. // // For example, __builtin_dump_struct would expand to a PseudoObjectExpr // that includes a couple of calls to a printf function. Printing parameter // names for that anyway would end up with duplicate parameter names (which, // however, got de-duplicated after visiting) for the printf function. - if (AST.getLangOpts().CPlusPlus && isa<PseudoObjectExpr>(S)) + if (isa<PseudoObjectExpr>(S)) return false; return true; } >From 8813a4f11254f89feb72e435888d896911a5dc78 Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Tue, 7 Nov 2023 14:22:07 +0800 Subject: [PATCH 3/4] Only apply the restriction to __builtin_dump_struct --- clang-tools-extra/clangd/InlayHints.cpp | 18 +++++++++--------- .../clangd/unittests/InlayHintTests.cpp | 9 ++++++--- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 1b54b570c1c5d4fc..9897d1c1e6da209e 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -590,15 +590,15 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { } bool dataTraverseStmtPre(Stmt *S) { - // Do not show inlay hints for PseudoObjectExprs. They're never - // genuine user codes. - // - // For example, __builtin_dump_struct would expand to a PseudoObjectExpr - // that includes a couple of calls to a printf function. Printing parameter - // names for that anyway would end up with duplicate parameter names (which, - // however, got de-duplicated after visiting) for the printf function. - if (isa<PseudoObjectExpr>(S)) - return false; + // Do not show inlay hints for the __builtin_dump_struct, which would expand + // to a PseudoObjectExpr that includes a couple of calls to a printf + // function. Printing parameter names for that anyway would end up with + // duplicate parameter names (which, however, got de-duplicated after + // visiting) for the printf function. + if (auto *POE = dyn_cast<PseudoObjectExpr>(S)) + if (auto *CE = dyn_cast<CallExpr>(POE->getSyntacticForm()); + CE && CE->getBuiltinCallee() == Builtin::BI__builtin_dump_struct) + return false; return true; } diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index 2b6c27b17b537a96..47af261fad850e84 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -1729,7 +1729,7 @@ TEST(ParameterHints, PseudoObjectExpr) { struct S { __declspec(property(get=GetX, put=PutX)) int x[]; int GetX(int y, int z) { return 42 + y; } - void PutX(int y) { x = y; } // Not `x = y: y` + void PutX(int y) { x = $one[[y]]; } // FIXME: Undesired `x = y: y` for this ill-formed expression. }; int printf(const char *Format, ...); @@ -1738,14 +1738,17 @@ TEST(ParameterHints, PseudoObjectExpr) { S s; __builtin_dump_struct(&s, printf); // Not `Format: __builtin_dump_struct()` printf($Param[["Hello, %d"]], 42); // Normal calls are not affected. - return s.x[1][2]; // Not `x[y: 1][z: 2]` + return s.x[ $two[[1]] ][ $three[[2]] ]; // `x[y: 1][z: 2]` } )cpp"); auto TU = TestTU::withCode(Code.code()); TU.ExtraArgs.push_back("-fms-extensions"); auto AST = TU.build(); EXPECT_THAT(inlayHints(AST, std::nullopt), - ElementsAre(HintMatcher(ExpectedHint{"Format: ", "Param"}, Code))); + ElementsAre(HintMatcher(ExpectedHint{"y: ", "one"}, Code), + HintMatcher(ExpectedHint{"Format: ", "Param"}, Code), + HintMatcher(ExpectedHint{"y: ", "two"}, Code), + HintMatcher(ExpectedHint{"z: ", "three"}, Code))); } TEST(ParameterHints, ArgPacksAndConstructors) { >From c88aad6d290cb8e2732f7fae71cb2ea2ecf0abda Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Mon, 20 Nov 2023 00:14:17 +0800 Subject: [PATCH 4/4] Override TraversePseudoObjectExpr --- clang-tools-extra/clangd/InlayHints.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 9897d1c1e6da209e..b460baffee8802d4 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -589,17 +589,22 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> { return true; } - bool dataTraverseStmtPre(Stmt *S) { - // Do not show inlay hints for the __builtin_dump_struct, which would expand - // to a PseudoObjectExpr that includes a couple of calls to a printf - // function. Printing parameter names for that anyway would end up with - // duplicate parameter names (which, however, got de-duplicated after + bool TraversePseudoObjectExpr(PseudoObjectExpr *E) { + // Do not show inlay hints for the __builtin_dump_struct, which would + // expand to a PseudoObjectExpr that includes a couple of calls to a + // printf function. Printing parameter names for that anyway would end up + // with duplicate parameter names (which, however, got de-duplicated after // visiting) for the printf function. - if (auto *POE = dyn_cast<PseudoObjectExpr>(S)) - if (auto *CE = dyn_cast<CallExpr>(POE->getSyntacticForm()); - CE && CE->getBuiltinCallee() == Builtin::BI__builtin_dump_struct) - return false; - return true; + if (auto *CE = dyn_cast<CallExpr>(E->getSyntacticForm()); + CE && CE->getBuiltinCallee() == Builtin::BI__builtin_dump_struct) + // Only traverse the syntactic forms. This leaves the door open in case + // the arguments in the syntactic form for __builtin_dump_struct could + // possibly get parameter names. + return RecursiveASTVisitor<InlayHintVisitor>::TraverseStmt( + E->getSyntacticForm()); + // FIXME: Shall we ignore semantic forms for other pseudo object + // expressions? + return RecursiveASTVisitor<InlayHintVisitor>::TraversePseudoObjectExpr(E); } bool VisitCallExpr(CallExpr *E) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits