This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Add modernize-printf-to-std-print check
ClosedPublic

Authored by mikecrowe on Apr 26 2023, 12:09 PM.

Details

Summary

Add FormatStringConverter utility class that is capable of converting
printf-style format strings into std::print-style format strings along
with recording a set of casts to wrap the arguments as required and
removing now-unnecessary calls to std::string::c_str() and
std::string::data()

Use FormatStringConverter to implement a new clang-tidy check that is
capable of converting calls to printf, fprintf, absl::PrintF,
absl::FPrintF, or any functions configured by an option to calls to
std::print and std::println, or other functions configured by options.

In other words, the check turns:

fprintf(stderr, "The %s is %3d\n", description.c_str(), value);

into:

std::println(stderr, "The {} is {:3}", description, value);

if it can.

std::print and std::println can do almost anything that standard printf
can, but the conversion has some some limitations that are described in
the documentation. If conversion is not possible then the call remains
unchanged.

Depends on D153716

Diff Detail

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
PiotrZSL added inline comments.
clang-tools-extra/clang-tidy/modernize/PrintfToStdPrintCheck.cpp
28 ↗(On Diff #517262)
NOTE: Consider using fully qualified names, like ::printf
45 ↗(On Diff #517262)

TK_IgnoreUnlessSpelledInSource should be fine for this.

68 ↗(On Diff #517262)

start warning with lower case, and maybe something like "use %0 instead of %1" (or whatever)

clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
33–48
NOTE: Consider re-ordering private-public, like in other files, to first put public stuff, then private.
Eugene.Zelenko added inline comments.
clang-tools-extra/clang-tidy/modernize/PrintfToStdPrintCheck.cpp
66 ↗(On Diff #517262)

Please don't use auto unless type is explicitly stated in same statement or iterator.

clang-tools-extra/clang-tidy/modernize/PrintfToStdPrintCheck.h
15 ↗(On Diff #517262)

Should be elaborated or removed.

clang-tools-extra/docs/ReleaseNotes.rst
222

Please keep alphabetical order (by check name) in this section.

clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst
6 ↗(On Diff #517262)

Please make first statement same as in Release Notes. Please highlight language constructs (like printf) with double back-ticks.

11 ↗(On Diff #517262)

Please prepend with .. code-block:: c++ line. Same for other snippets.

73 ↗(On Diff #517262)

Please add information about default value.

Thanks for all the reviews.

It may be a good idea to create unittests for the formatconverter in clang-tools-extra/unittests/clang-tidy/

I started there but had decided that the easiest and most reviewable form for the tests was in lit tests since the code that uses FormatStringConverter is so simple. (Particularly since I was hoping to persuade the inventor of std::format to review the tests too.) Are you proposing that I should duplicate (most of) the lit tests in the unit tests or migrate most of the lit tests to unit tests? Are there any existing tests that do similar things that I should model them on?

mikecrowe marked 12 inline comments as done.Apr 29 2023, 8:33 AM

Thank you for all the review comments.

clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
323

Good spot. This was wider than I intended. The cast is only supposed to be used if the argument is a pointer to unsigned char or signed char.

I think that I probably ought to make sure that all the places that decide that conversion is not possible emit a warning explaining why.

413

Good spot. I'm sure I used the right cast in an earlier version... :(

clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst
73 ↗(On Diff #517262)

The current implementation always "fixes" printf, fprintf, absl::PrintF and absl::FPrintf, even when this option is used (see UseStdPrintCheck constructor.) Should the option inhibit this default?

92 ↗(On Diff #517262)

I shall investigate how to do that.

Eugene.Zelenko added inline comments.Apr 29 2023, 9:02 AM
clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst
73 ↗(On Diff #517262)

It may be reasonable to provide possibility to override default.

mikecrowe marked 4 inline comments as done.Apr 30 2023, 7:33 AM
mikecrowe added inline comments.
clang-tools-extra/docs/clang-tidy/checks/modernize/printf-to-std-print.rst
61 ↗(On Diff #517262)

I think that's probably a good idea. The casts are ugly, and probably unnecessary in many cases. I've implemented it, but I'm currently wrestling with the lit tests for it.

73 ↗(On Diff #517262)

I think it's likely that anyone using a custom value for either PrintfLikeFunctions or FPrintfLikeFunctions won't want the default function list for either.

mikecrowe marked an inline comment as done.Apr 30 2023, 7:49 AM
mikecrowe added inline comments.
clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert.cpp
289 ↗(On Diff #517262)

This requires a cast to unsigned char. It appears that Arg->getType()->isSignedIntegerType() inside the uArg case is returning false for signed char, which means that it doesn't get one. Strange!

mikecrowe added inline comments.Apr 30 2023, 8:03 AM
clang-tools-extra/test/clang-tidy/checkers/modernize/printf-to-std-print-convert.cpp
289 ↗(On Diff #517262)

This requires a cast to unsigned char. It appears that Arg->getType()->isSignedIntegerType() inside the uArg case is returning false for signed char, which means that it doesn't get one. Strange!

Operator error. Apologies for the noise. :(

mikecrowe updated this revision to Diff 518315.Apr 30 2023, 8:05 AM

I've addressed most of the review comments. The work that remains outstanding is:

  • Emit warnings when conversion is not possible explaining why.
  • Only add signed/unsigned casts when in StrictMode.
  • Automatically remove now-unnecessary calls to c_str() in arguments rather than requiring readability-redundant-string-cstr check to be run afterwards.
njames93 added inline comments.May 6 2023, 9:29 AM
clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h
21

This will need rebasing and changing to LangOpts.CPlusPlus23

clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
409–414

Is it not nicer to just search for the compliment

clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
58

Don't need to specify virtual here when the function is marked override

clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
45–46

This should be relatively easy to address, just look at how other checks use the IncludeInserter to add includes.

clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
125–127

It would be nice if the there was support for changing this to std::println("Integer {:d} from bool", b);

mikecrowe marked 3 inline comments as done.May 8 2023, 8:46 AM
mikecrowe added inline comments.
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
125–127

Yes. That was item 2 on the plans for the future in my first comment. Would you prefer that everything is completed in this single commit, or would you be happy to the core functionality first with future enhancements in separate commits afterwards?

mikecrowe marked 2 inline comments as done.May 8 2023, 10:51 AM
mikecrowe updated this revision to Diff 520439.May 8 2023, 10:52 AM

Address many more review comments, including:

  • Only add casts for signed/unsigned discrepancy if StrictMode option is set.
  • Use IncludeInserter to add <print> or other required header.

Review comments still outstanding:

  • Use println if format string ends in \n.
  • Remove c_str() as part of the same check (I'm not really sure how to do this, are there any other checks that I should look at for inspiration?)
  • Emit warnings to explain why if conversion is not possible.
mikecrowe added inline comments.May 11 2023, 1:31 PM
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
118

Is PrintFunction (and the soon-to-arrive PrintlnFunction) distinct enough from PrintfLikeFunctions and FprintfLikeFunctions? Should I use ReplacementPrintFunction instead?

mikecrowe added inline comments.May 14 2023, 7:51 AM
clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
28

This apparently need to be Ty->getUnqualifiedDesugaredType() to ensure that arguments like std::string().c_str() are correctly treated as being of char type. Without, the dyn_cast<BuiltinType> fails.

mikecrowe marked an inline comment as done.May 15 2023, 12:32 PM

Implement review comments

I believe that I've now addressed all review comments. In particular:

  • Use println if format string ends in \n, which required adding an extra replacement function configuration option.
  • Remove c_str as part of the same check. I'm not really sure whether I've done this the right way, but it seems to work. I split some functionality out of the existing readability-redundant-string-cstr check in a separate change to support this. I needed to add an isRealChar AST matcher, which might be better somewhere else.
  • Warnings are now emitted to explain why conversion is not possible.

In addition, I have also:

  • Greatly improved turning signed integer types into their unsigned equivalents and vice-versa so that fixed-width integer types are now supported whether in the std namespace or not. This required adding dummy cstddef and cstdint headers.
  • Added and fixed bugs in a few other test cases.
mikecrowe edited the summary of this revision. (Show Details)May 15 2023, 12:35 PM
mikecrowe edited the summary of this revision. (Show Details)
mikecrowe updated this revision to Diff 523531.May 18 2023, 1:18 PM

Minor updates

  • Use -std=c++23 rather than -std=c++2b in lit checks
  • Enable check on C++23-and-later only if using std::println too
  • Add comment in the style of add_new_check.py to UseStdPrintCheck
  • Insert check in correct sorted location in docs/clang-tidy/checks/list.rst
mikecrowe added inline comments.May 20 2023, 5:46 AM
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
80

It turns out that absl::PrintF and absl::FPrintF work like std::format, fmt::printf, etc. and use the signedness of the argument rather than the signedness indicated in the format string to determine how to format the number. In other words:
unsigned int ui = 0xffffffff; absl::PrintF("%d\n", ui); yields 4294967295 (see https://godbolt.org/z/dYcbehxP9 ), so the casts that StrictMode adds would change the behaviour of the converted code.

I can think of several ways around this:

  1. Update the documentation to explain this, recommending not to use StrictMode when converting Abseil functions.
  1. Remove built-in support for Abseil functions from this check. Anyone wishing to convert them can do so via the customisation features, and can choose not to use StrictMode. (This could be documented here.)
  1. Teach the code to recognise whether the arguments is being passed as a C-style variable argument list or as fully-typed arguments to a templated function and make StrictMode only add the casts for the former. (I've not investigated how feasible this is.)
  1. Treat the known Abseil functions in this check differently by name and disable the casting behaviour. This means that conversion from fmt::printf via the customisation mechanism wouldn't automatically get that behaviour.

As someone who doesn't use Abseil I'm inclined towards option 2, with the possibility of implementing option 3 in a separate commit later. I'm not particularly keen on the other two options.

mikecrowe updated this revision to Diff 527187.May 31 2023, 1:35 PM

Don't add casts when converting absl::PrintF and similar with StrictMode.

Remove extra space in release notes.

mikecrowe added inline comments.May 31 2023, 1:36 PM
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
80

It turns out that option 3 was easier to implement than I expected, so I've implemented it in the latest version.

Rebase, stop including Optional.h which has been removed but wasn't
necessary anyway.

PiotrZSL added inline comments.Jun 13 2023, 11:43 AM
clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
44–45

this code is already duplicated, move it to some separate private function, like isCpp23PrintConfigured or something...

57

Those TK_IgnoreUnlessSpelledInSource should be moved into getCheckTraversalKind()

clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h
34

missing store function, to properly export configuration via --export-config

41

I heard that using clang::tooling::HeaderIncludes is more recommended.
And this is just some house-made stuff

clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
38–40
NOTE: no need fore else or {}
186

This may crash for wchar, maybe better limit StringLiteral to Ordinary and UTF8 or only Ordinary

190

magic number

203

this function should be split into smaller one.

231

general: no need for else after return

385–398

constant construction of those marchers may be costly.. can be cache them somehow in this object ?

419

maybe put that getType into some local variable, instead of constantly referencing it...

mikecrowe marked 6 inline comments as done.Jun 18 2023, 9:58 AM

Thanks for the comprehensive review.

clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
44–45

You're correct that ReplacementPrintFunction == "std::print" || ReplacementPrintlnFunction == "std::println" is duplicated in isLanguageVersionSupported, but in that code we're considering which C++ version the functions require and in this code we're considering which header the functions require. These are not the same question. It just so happens that these checks are against the same function names now, but they need not be. If another function is added to <print> in C++26 and this code ends up being able to convert to it then the checks would need to diverge.

Nevertheless, I will do as you request if you still think it's worthwhile.

57

Ah, that was added since I wrote the original version of this check. I'll address this.

clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h
41

I'm afraid that I don't really understand this comment. The use of IncludeInserter is far more common in the existing checks than HeaderIncludes and from looking at IncludeCleaner.cpp the use of the latter is rather more complex. New features were being added to IncludeInserter within the last six months. I'm unsure what "house-made" means in the context of the IncludeInserter code that I didn't write.

Do you have anything more concrete than hearsay? If there is a plan to deprecate IncludeInserter then it feels like something closer to its convenient interface would need to be implemented in terms of HeaderIncludes for checks to use rather than them duplicating the code in IncludeCleaner.cpp.

If you can explain what you'd like me to do, and ideally provide pointers to similar things being done elsewhere then perhaps I can address this comment.

clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
186

It doesn't look like there's any support for u8 literals in printf or std::print (yet), so I think just Ordinary is sufficient.

203

I agree. I'm surprised it hasn't come up in review earlier. I tried to do so prior to pushing the very first version of this for review and gave up since the parts ended up referring to so many local variables making the code even harder to understand than it is now. I will have another attempt.

231

In general, you're correct that I've used else after return in other places and I will fix them. However, in this case the else is required since the very first if block above doesn't have a return. (Hopefully this complexity will go away if I succeed in splitting this function up.)

385–398

Good idea. Do you have any pointers to code that does this? I couldn't find any.

The types involved all seem to be in the internal:: namespace and presumably subject to change. Ideally, I'd put:

std::optional<SomeSortOfMatcherType> StringCStrCallExprMatcher;

in the class and then populate it here the first time lazily. Unfortunately I have no idea what type to use for SomeSortOfMatcherType.

mikecrowe marked 2 inline comments as done.

Address a subset of the review comments

I've addressed some of PiotrZSL's review comments, so it seemed worth
'posting this update here, but I don't believe that this version
'needs reviewing until I receive responses to my questions and/or
'I've attempted to split the HandlePrintfSpecifier method.

PiotrZSL accepted this revision.Jun 18 2023, 1:49 PM

Except readability issues with this check code (bunch of else, ..), and that I didn't took a deep dive into format string conversion (I hope that author is right there).
I would say that this check probably could be delivered. Would be nice to run it on some test projects, just to be sure that it wont crash or wont produce too much false-positives.
I still would expect that probably there can be some issues with it...

Next steps for this check would be:

  • Fix some known (breaking) issues (like option naming)
  • Deliver check to main
  • Refactor code for performance / readability.
  • Deliver code refactor.

Once on main branch, check can be tested by other users, and there is a chance that some issues with it could be found before branch-out.

clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
118

Personally I would invert this, if (!...canApply()) { diag(PrintfCall->getBeginLoc(), "unable to use '%0' instead of %1 because %2") << ...; return; }

119

no need to assign this to Diag, it will be destroyed anyway, just call diag.

clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
28

no need for anonymous namespace per LLVM codding standard, use static keyword for all functions, put them all into clang::tidy::utils namespace

147–149

do not put matchers into clang::ast_matchers to avoid ODR issues. put it into anonymous namespace under clang::tidy::utils

158–176

consider moving this into separate function that take Call and StrictMode as an argument this isn't readable. make function static.

385–398

clang::ast_matchers::StatementMatcher<CXXMemberCallExpr>, this is defined as using clang::ast_matchers::StatementMatcher = typedef internal::Matcher<Stmt>.
I would create it in class constructor as private member.

clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
118

Use Replacement. It will be way better.

This revision is now accepted and ready to land.Jun 18 2023, 1:49 PM
mikecrowe added inline comments.Jun 18 2023, 1:53 PM
clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
203

It turns out that things are working out much better in my second attempt at splitting this function. I shall address the other new review comments before sending another revision for review though.

mikecrowe marked 7 inline comments as done.Jun 24 2023, 7:03 AM

I'm still working on the remaining items.

clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
231

I've now reworked this function extensively, so there's no longer an else here.

clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
118

I assume that you mean ReplacementPrintFunction. (I see ReplacementString used in other checks, so I think that just Replacement might be a bit vague.)

PiotrZSL added inline comments.Jun 24 2023, 7:15 AM
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
118

Yes, ... ReplacementPrintFunction

mikecrowe marked 4 inline comments as done.Jun 24 2023, 8:22 AM
mikecrowe added inline comments.
clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
385–398

Thanks for the pointer. It turns out that I need just clang::ast_matchers::StatementMatcher.

mikecrowe updated this revision to Diff 534221.Jun 24 2023, 8:33 AM
mikecrowe marked an inline comment as done.

Address review comments from PiotrZSL

  • Name options ReplacementPrintFunction and ReplacementPrintlnFunction
  • Use separate function not lambda in FormatStringConverter constructor
  • Put isRealChar matcher outside clang::ast_matchers
  • Remove anonymous namespace as suggested by PiotrZSL
  • Split HandlePrintfSpecifier body into separate functions
  • Make ArgKind a constant rather than calling Spec.getKind() every time
  • Other simplifications, method renaming, comments and cleanups
mikecrowe edited the summary of this revision. (Show Details)Jun 24 2023, 8:42 AM
mikecrowe edited the summary of this revision. (Show Details)
Eugene.Zelenko added inline comments.Jun 24 2023, 9:02 AM
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
30

Please use single back-ticks for -Wformat (command-line option).

82

Please highlight true with back-ticks.

88

Please use single back-ticks for StrictMode (option).

104

Please highlight false and numbers with back-ticks.

113

Please use single back-ticks for FprintfLikeFunctions (option). Same for printf; absl::PrintF below.

123

Ditto.

145

Please use single back-ticks for ReplacementPrintFunction (option).

@Eugene.Zelenko,
I will make the documentation changes you've suggested, but I can't say I really understand which document elements require single backticks and which require dual backticks. https://llvm.org/docs/SphinxQuickstartTemplate.html seems to imply that single backticks are only used for links and double backticks are used for monospace, but it's not completely clear. Most of the existing documentation seems to be consistent with what you've suggested though.

mikecrowe marked 7 inline comments as done.Jun 24 2023, 9:28 AM
mikecrowe updated this revision to Diff 534227.Jun 24 2023, 9:29 AM
mikecrowe edited the summary of this revision. (Show Details)

Apply documentation backtick changes suggested by Eugene.Zelenko

@Eugene.Zelenko,
I will make the documentation changes you've suggested, but I can't say I really understand which document elements require single backticks and which require dual backticks. https://llvm.org/docs/SphinxQuickstartTemplate.html seems to imply that single backticks are only used for links and double backticks are used for monospace, but it's not completely clear. Most of the existing documentation seems to be consistent with what you've suggested though.

In short: double back-ticks are for language constructs. Single - for command-line options, options and their values.

PiotrZSL accepted this revision.Jun 24 2023, 9:53 AM
PiotrZSL added inline comments.
clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
38

those 2 looks in-depended. Cannot they be put as default value into Option config ?

71

call this function only if PrintfLikeFunctions is not empty.

79

call this function only if FprintfLikeFunctions is not empty

80

this could match also methods, maybe something unless(cxxMethodDecl()) ?

83

consider moving this stringLiteral to be first, consider adding something like unless(argumentCountIs(0)), unless(argumentCountIs(1))` at begining or create matcher that verify first that argument count is >= 2, so we could exlude most of callExpr at begining, even before we match functions

clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
59
60
61
62
mikecrowe marked 2 inline comments as done.Jun 24 2023, 2:00 PM

Thanks for the further reviews.

clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
38

My expectation was that if you didn't want to replace printf (and instead wanted to replace some other printf-like function) then you'd also not want to replace fprintf and vice-versa. In my head the two options do go together. If setting one didn't also remove the default for the other you'd end up having to specify PrintfLikeFunctions=my_printf, FPrintfLikeFunctions= just to replace a single function.

80

I would like to be able to match methods. The code I wrote this check to run on has classes that have methods that used to call std::fprintf, and currently call fmt::fprintf. I wish to convert those methods to use fmt::print and use this check to fix all their callers. Eventually I hope to be able to move to std::print.

However, the check doesn't currently seem to work for methods since the arguments are off-by-one and the replacement is incorrect too. I'll add the unless(cxxMethodDecl) checks for now and support can be added later.

83

I would have hoped that hasArgument would fail quite fast if the argument index passed is greater than the number of arguments. I will add argumentCountAtLeast and use it regardless though.

Address further review comments from PiotrZSL

  • Only add matchers if they are required.
  • Check the number of arguments right at the start of the matcher using the new argumentCountAtLeast matcher added in D153716.
  • Apply further documentation backtick changes.
mikecrowe edited the summary of this revision. (Show Details)Jun 24 2023, 11:51 PM
mikecrowe marked 2 inline comments as done.
PiotrZSL accepted this revision.Jun 25 2023, 8:56 AM

Consider delivering this check. I do not think that it will become much better with more refactoring.

clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
203–204

this check for isOrdinary could be done on matcher level, just add anonymous matcher, and use it there, you can still use it also here, but my idea is to reduce amount of calls to check method.

AST_MATCHER(StringLiteral, isOrdinary) {
  return Node.isOrdinary();
}
mikecrowe updated this revision to Diff 534354.Jun 25 2023, 9:23 AM

Include isOrdinary in check as suggested by @PiotrZSL.

Thanks for all the reviews.

@PiotrZSL, if you think that this patch, and its dependency are ready
to land then please can you do so? I don't have permission to do so
myself.

mikecrowe marked an inline comment as done.Jun 25 2023, 9:23 AM
mikecrowe added inline comments.Jun 25 2023, 9:54 AM
clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
65

This is going to write the default value set in the constructor if ReplacementPrintFunction is std::print or ReplacementPrintlnFunction is std::println even if PrintHeader was not specified in the configuration. I don't know how much of a problem this is.

This revision was automatically updated to reflect the committed changes.
thakis added a subscriber: thakis.Jun 25 2023, 12:12 PM

This breaks tests on windows: http://45.33.8.238/win/80283/step_8.txt

Please take a look and revert for now if it takes a while to fix.

PiotrZSL reopened this revision.Jun 25 2023, 12:43 PM

@thakis Thank you.

clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
10–16

Those includes need to be removed. We cannot use system includes, some dummy one can be used only.

This revision is now accepted and ready to land.Jun 25 2023, 12:43 PM
mikecrowe updated this revision to Diff 534370.Jun 25 2023, 1:31 PM

Add dummy <inttypes.h> header for tests

This header is hopefully correct for LP64 and P64, but I haven't tested it
on anything other than x86_64 Linux yet.

This breaks tests on windows: http://45.33.8.238/win/80283/step_8.txt

Please take a look and revert for now if it takes a while to fix.

Thanks for letting me know, I thought I could get away with including <inttypes.h> from a test since it is a compiler header rather than a libc header.

I've added a potential fix, but I don't have a Windows machine (or many other targets) to test it on. Is there a way to get this change to run through the buildbots without landing it?

mikecrowe marked an inline comment as done.Jun 25 2023, 1:48 PM
mikecrowe added inline comments.
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
10–16

I believe that <inttypes.h> is the only one that isn't present in test/clang-tidy/checkers/Inputs/Headers/. Hopefully adding it will have been sufficient.

None i know of, but given the bot's already red, you won't make it worse :)

Tests shouldn't include any headers generally, not even inttypes.h (unless the test tests that header).

This revision was automatically updated to reflect the committed changes.
PiotrZSL added inline comments.Jun 26 2023, 2:12 AM
clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstddef
12

We shouldn't include this stddef.h, it's being included from system headers.

PiotrZSL reopened this revision.Jun 26 2023, 2:52 AM
This revision is now accepted and ready to land.Jun 26 2023, 2:52 AM
mikecrowe marked an inline comment as done.Jun 26 2023, 4:27 AM

It looks like the char test is failing on targets where unadorned char is unsigned. I have access to two such machines, so I ought to be able to reproduce this myself (either on the up-to-date slow one, or the fast one that lacks a sufficiently-new cmake.)

@thakis, http://45.33.8.238/win/80313/summary.html makes it looks like Windows may be happy now, but I may be misinterpreting the results.

mikecrowe added inline comments.Jun 26 2023, 9:41 AM
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
170

This should have a cast to signed char if StrictMode=true. That cast is currently there by accident on targets where char is unsigned, but not on targets where char is signed. This is a real problem, but luckily one that's easy to fix.

Fix tests on targets where char is unsigned

We need to cast chars to to signed char if we want to guarantee that
they are formatted as signed numbers on all targets.

Improve char formatting tests a little too.

Add dummy stddef.h header

This revision was landed with ongoing or failed builds.Jun 26 2023, 12:05 PM
This revision was automatically updated to reflect the committed changes.

Despite the fact that I've worked on what became this check for about two years, now that it's landed I've suddenly spotted a significant flaw: printf returns the number of characters printed, whereas std::print doesn't return anything. None of my test cases made use of the return value. I think this means that I need to only match on calls that don't make use of the return value. I shall try to do that.

Despite the fact that I've worked on what became this check for about two years, now that it's landed I've suddenly spotted a significant flaw: printf returns the number of characters printed, whereas std::print doesn't return anything. None of my test cases made use of the return value. I think this means that I need to only match on calls that don't make use of the return value. I shall try to do that.

You can provide warning, but without fix. But that would need to be put into documentation.
If we lucky, and there will be no issues with current version, then you can put this in separate patch.
Anyway I do not think that many project use printf, most probably they use std::cout, fmt::format or some other custom wrapper around something.