-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Turn invented Exprs' source locations in __builtin_dump_struct to empty #72750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…t to empty This reflects the comment in llvm#71366 (comment). As that PR suggests, the invented CallExpr's source location previously pointed to the beginning of the __builtin_dump_struct. These spurious AST nodes confused clangd while displaying parameter inlay hints. This patch takes another approach to address the same issue, by turning the location for each _argument_ within an invented call to printf to empty, (maybe) at the risk of breaking the invariant for CallExpr -- The source location for an argument could be invalid from now on.
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangd Author: Younan Zhang (zyn0217) ChangesThis reflects the comment in #71366 (comment). As that PR suggests, the invented CallExpr's source location previously pointed to the beginning of the This patch takes another approach to address the same issue, by turning the location for each argument within an invented call to printf to empty, (maybe) at the risk of breaking the invariant for CallExpr -- The source location for an argument could be invalid from now on. Full diff: https://github.com/llvm/llvm-project/pull/72750.diff 2 Files Affected:
diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index 20c1cdd985dbc01..47af261fad850e8 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -1724,6 +1724,33 @@ 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 = $one[[y]]; } // FIXME: Undesired `x = y: y` for this ill-formed expression.
+ };
+
+ 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[ $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{"y: ", "one"}, Code),
+ HintMatcher(ExpectedHint{"Format: ", "Param"}, Code),
+ HintMatcher(ExpectedHint{"y: ", "two"}, Code),
+ HintMatcher(ExpectedHint{"z: ", "three"}, Code)));
+}
+
TEST(ParameterHints, ArgPacksAndConstructors) {
assertParameterHints(
R"cpp(
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ae588db02bbe722..5d348bd712dd104 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -454,13 +454,13 @@ namespace {
struct BuiltinDumpStructGenerator {
Sema &S;
CallExpr *TheCall;
- SourceLocation Loc = TheCall->getBeginLoc();
+ SourceLocation Loc;
SmallVector<Expr *, 32> Actions;
DiagnosticErrorTrap ErrorTracker;
PrintingPolicy Policy;
BuiltinDumpStructGenerator(Sema &S, CallExpr *TheCall)
- : S(S), TheCall(TheCall), ErrorTracker(S.getDiagnostics()),
+ : S(S), TheCall(TheCall), Loc(), ErrorTracker(S.getDiagnostics()),
Policy(S.Context.getPrintingPolicy()) {
Policy.AnonymousTagLocations = false;
}
@@ -491,7 +491,7 @@ struct BuiltinDumpStructGenerator {
// Register a note to explain why we're performing the call.
Sema::CodeSynthesisContext Ctx;
Ctx.Kind = Sema::CodeSynthesisContext::BuildingBuiltinDumpStructCall;
- Ctx.PointOfInstantiation = Loc;
+ Ctx.PointOfInstantiation = TheCall->getBeginLoc();
Ctx.CallArgs = Args.data();
Ctx.NumCallArgs = Args.size();
S.pushCodeSynthesisContext(Ctx);
|
The CI run shows the test Sema/builtin-dump-struct.c is failing. |
It looks like the issue is, if the invented CallExpr is ill-formed and the compiler needs to issue a diagnostic about it, with the invalid SourceLocation it doesn't have a source location to attach to the diagnostic. I guess this means the approach of using an invalid SourceLocation doesn't work after all? |
Oops, I didn't even realize there's such a test for C. I had only run the Sema/builtin-dump-struct.cpp locally and it passed. :(
The answer seems no to me. At least we have to preserve these source locations at the Sema level to produce the diagnoses. As to the other approach involving "virtual buffers", I think that requires a more drastic change. I.e. moving the printf function generation to the tokenization level. Closing this PR now and sorry for the churn! |
This reflects the comment in #71366 (comment).
As that PR suggests, the invented CallExpr's source location previously pointed to the beginning of the
__builtin_dump_struct
. These spurious AST nodes confused clangd while displaying parameter inlay hints.This patch takes another approach to address the same issue, by turning the location for each argument within an invented call to printf to empty, (maybe) at the risk of breaking the invariant for CallExpr -- The source location for an argument could be invalid from now on.