Format function arg defaults with the constants-as-written printer - #1069
Format function arg defaults with the constants-as-written printer#1069conrade-ctc wants to merge 2 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1069 +/- ##
==========================================
+ Coverage 87.68% 87.70% +0.01%
==========================================
Files 23 23
Lines 6382 6391 +9
==========================================
+ Hits 5596 5605 +9
Misses 786 786
🚀 New features to boost your workflow:
|
| // is not a plain literal. | ||
| errno = 0; | ||
| char* ParseEnd = nullptr; | ||
| double DefaultArgValue = std::strtod(Result.c_str(), &ParseEnd); |
There was a problem hiding this comment.
Maybe we can take a step back here -- is that the way clang does this?
There was a problem hiding this comment.
good point... claude pointed out to me that there is a more standard, generic fix... two possibilities... let me try that them, and repost... might close one of the two PRs actually, since they are related. Give me a sec...
There was a problem hiding this comment.
Good call — reworked. It now does what SemaCodeComplete's GetDefaultValueString does: read the parameter's getDefaultArgRange() source text via Lexer::getSourceText (including stripping the sometimes-present leading =, per the FIXME there), falling back to the AST pretty-print only when there's no usable range. That makes the output as-written by construction, so the float-precision FIXME and the std::stod normalization are gone entirely. Literal defaults now render exactly as written (4.0 where the old code produced 4.) — existing test expectations updated to match.
|
clang-tidy review says "All clean, LGTM! 👍" |
189b6aa to
2d07020
Compare
|
clang-tidy review says "All clean, LGTM! 👍" |
2d07020 to
1bc99c8
Compare
| // Render the default as written: read its source range, the way clang's | ||
| // own code completion formats default arguments (GetDefaultValueString | ||
| // in SemaCodeComplete). Pretty-printing the AST instead reproduces | ||
| // floating literals at representation precision ("3.1400000000000001" |
There was a problem hiding this comment.
I believe that's a bug in clang -- it should print the value as written. Can we follow up there, and land that as a temporary workaround?
There was a problem hiding this comment.
makes sense, i'll iterate on that and reproducing the bug upstream. i'll post a PR for that separately, and we can treat this as a work-around. I'll update this PR as well with the proper guards so that we can clean up later.
There was a problem hiding this comment.
also, in the process of iterating on the upstream, a lighter version of this diff that uses a different pathway was found, so i'm verifying it and probably will update this PR to swap in that change instead.
There was a problem hiding this comment.
Reworked: the patch now prints defaults with printPretty, the interpreter's ASTContext, and ConstantsAsWritten = true, instead of the hand-rolled source-text read. All existing tests pass unchanged. The clang-side precision bug is being fixed in llvm/llvm-project#218471; until then, defaults that ConstantsAsWritten cannot cover (cooked UDL floats, invalid-range literals) still print at maximum precision. A version-gated canary test expects the old output before clang 24 and the fixed output from clang 24 on, so a cherry-pick or a slipped landing shows up as a named failure.
2535e74 to
1c98a0f
Compare
| } | ||
| ASTContext& Ctx = getASTContext(); | ||
| PrintingPolicy Policy(Ctx.getLangOpts()); | ||
| Policy.ConstantsAsWritten = true; |
There was a problem hiding this comment.
Oh, that’s nice. And probably kills our upstream story probably for good.
There was a problem hiding this comment.
@vgvassilev, do you think the UDL hole that is listed above is worth a PR to clang as well? it's a separate gap that might be valuable to clean up.
There was a problem hiding this comment.
Oh, ok. Did not realize that’s a disk access. That’s pretty slow for the pch case and requires headers to be around..
There was a problem hiding this comment.
hmmm, by UDL i mean user-defined-literal, not the disk one :) Just want to make sure we're on the same page... there is apparently a minor hole in the UDL float impl that mixes 90.0_deg and 90._deg for example... claude identified that as a follow up that is related and needs a separate treatment upstream.
1c98a0f to
e900344
Compare
|
clang-tidy review says "All clean, LGTM! 👍" |
Print the default-argument expression with printPretty, the interpreter's ASTContext, and ConstantsAsWritten = true. The policy prints literal leaves from their source text, so defaults keep their spelling (4.0 stays "4.0"). This replaces the AST re-print at maximum float precision, which turned 3.14 into 3.1400000000000001. Co-developed-with-the-help-of: Claude Code (Fable 5, human in the loop)
Fails on the first LLVM that prints shortest round-trip floats (llvm/llvm-project#218471), which changes the output for defaults the constants-as-written policy cannot cover. Co-developed-with-the-help-of: Claude Code (Fable 5, human in the loop)
e900344 to
5c372a8
Compare
Print the default-argument expression with printPretty, the interpreter's ASTContext, and ConstantsAsWritten = true. The policy prints literal leaves from their source text, so defaults keep their spelling (4.0 stays "4.0"). This replaces the AST re-print at maximum float precision, which turned 3.14 into 3.1400000000000001. A canary test fails on the first LLVM that prints shortest round-trip floats (llvm/llvm-project#218471), which changes the output for defaults the policy cannot cover. Content matches compiler-research#1069. Co-developed-with-the-help-of: Claude Code (Fable 5, human in the loop)
GetFunctionArgDefaultre-printed default arguments at maximum float precision, so3.14rendered as3.1400000000000001. Print them withprintPretty, the interpreter'sASTContext, andConstantsAsWritten = trueinstead: literal leaves keep their source spelling (4.0stays4.0).Two clang-side gaps remain: the maximum-precision expansion where
ConstantsAsWrittencannot apply (fix under review in llvm/llvm-project#218471), and cooked UDL floats (90.0_degprints as90._deg). A canary test expects the old output before clang 24 and the fixed output from clang 24 on.