This is an archive of the discontinued LLVM Phabricator instance.

[NFC][Clang]Fix static analyzer tool remarks about large copies by values
ClosedPublic

Authored by Manna on May 2 2023, 5:51 AM.

Details

Summary

Reported by Static Analyzer Tool:

Inside "Format.cpp" file, in

clang::format::internal::reformat(clang::format::FormatStyle const &, llvm::StringRef, llvm::ArrayRef<clang::tooling::Range>, unsigned int, unsigned int, unsigned int, llvm::StringRef, clang::format::FormattingAttemptStatus *)::[lambda(clang::format::Environment const &) (instance 4)]::operator ()(clang::format::Environment const &): A very large function call parameter exceeding the high threshold is passed by value.
pass_by_value: Capturing variable S of type clang::format::FormatStyle (size 808 bytes) by value, which exceeds the high threshold of 512 bytes

This patch removes redundant capturing variable S and passes type clang::format::FormatStyle Expanded instead as parameter in functions: BracesInserter(), BracesRemover(), and SemiRemover().

Diff Detail

Event Timeline

Manna created this revision.May 2 2023, 5:51 AM
Herald added projects: Restricted Project, Restricted Project, Restricted Project. · View Herald TranscriptMay 2 2023, 5:51 AM
Manna requested review of this revision.May 2 2023, 5:51 AM
Manna edited the summary of this revision. (Show Details)May 2 2023, 5:56 AM
Manna edited the summary of this revision. (Show Details)May 2 2023, 9:52 AM
Manna added a reviewer: erichkeane.
erichkeane accepted this revision.May 2 2023, 9:58 AM
This revision is now accepted and ready to land.May 2 2023, 9:58 AM
tahonermann accepted this revision.May 2 2023, 9:58 AM

Looks good to me.

Manna added a comment.May 2 2023, 10:02 AM

Thank you @erichkeane and @tahonermann for reviews!

HazardyKnusperkeks requested changes to this revision.May 2 2023, 12:16 PM

But it is plain wrong.
It was done on purpose, so that e.g. RemoveBracesLLVM is not set when the SemiRemover does its work.

This revision now requires changes to proceed.May 2 2023, 12:16 PM

But it is plain wrong.
It was done on purpose, so that e.g. RemoveBracesLLVM is not set when the SemiRemover does its work.

Ah, shoot, you're right! I missed that the 'return' was in a lambda! Thanks for the good catch! I think this patch is just 'wrong' in its entirety, and this is a case where Coverity needs to be suppressed.

Thank you for catching that @HazardyKnusperkeks! I completely missed (somehow) that the changed code modified Expanded. I offered another suggestion.

clang/lib/Format/Format.cpp
3486–3489

How about using an init capture instead? This will suffice to avoid one of the copies but means that InsertBraces doesn't get set until the lambda is invoked. I wouldn't expect that to matter though.

tahonermann requested changes to this revision.May 2 2023, 12:50 PM
owenpan added inline comments.May 2 2023, 2:31 PM
clang/lib/Format/Format.cpp
3486–3489

I'm not sure if it's worth the trouble, but if I really had to bother, I would do something like the above.

Can you link to the Coverity issue so we can see what it was complaining about?

Can you link to the Coverity issue so we can see what it was complaining about?

Unfortunately this is from an internal-run of Coverity that Intel is running. I'd be shocked if it doesn't appear on the open-source/LLVM version though?

MyDeveloperDay edited the summary of this revision. (Show Details)May 3 2023, 11:02 AM
Manna added a comment.May 3 2023, 11:03 AM

Thanks @erichkeane for response.

@MyDeveloperDay, Our internal Coverity link won't work without login.
This is what Coverity was complaining about.

Big parameter passed by value
Copying large values is inefficient, consider passing by reference; Low, medium, and high size thresholds for detection can be adjusted.

  1. In clang::​format::​internal::​reformat(clang::​format::​FormatStyle const &, llvm::​StringRef, llvm::​ArrayRef<clang::​tooling::​Range>, unsigned int, unsigned int, unsigned int, llvm::​StringRef, clang::​format::​FormattingAttemptStatus *)::​[lambda(clang::​format::​Environment const &) (instance 5)]::​operator ()(clang::​format::​Environment const &): A very large function call parameter exceeding the high threshold is passed by value. (CWE-398)

if (Style.RemoveSemicolon) {
3499 FormatStyle S = Expanded;
3500 S.RemoveSemicolon = true;

pass_by_value: Capturing variable S of type clang::format::FormatStyle (size 572 bytes) by value, which exceeds the high threshold of 512 bytes.

3501 Passes.emplace_back([&, S](const Environment &Env) {
3502 return SemiRemover(Env, S).process(/*SkipAnnotation=*/true);
3503 });
3504 }

  1. In clang::​format::​internal::​reformat(clang::​format::​FormatStyle const &, llvm::​StringRef, llvm::​ArrayRef<clang::​tooling::​Range>, unsigned int, unsigned int, unsigned int, llvm::​StringRef, clang::​format::​FormattingAttemptStatus *)::​[lambda(clang::​format::​Environment const &) (instance 4)]::​operator ()(clang::​format::​Environment const &): A very large function call parameter exceeding the high threshold is passed by value. (CWE-398)

if (Style.RemoveBracesLLVM) {
3491 FormatStyle S = Expanded;
3492 S.RemoveBracesLLVM = true;

pass_by_value: Capturing variable S of type clang::format::FormatStyle (size 572 bytes) by value, which exceeds the high threshold of 512 bytes.

3493 Passes.emplace_back([&, S](const Environment &Env) {
3494 return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);
3495 });
3496 }

  1. In clang::​format::​internal::​reformat(clang::​format::​FormatStyle const &, llvm::​StringRef, llvm::​ArrayRef<clang::​tooling::​Range>, unsigned int, unsigned int, unsigned int, llvm::​StringRef, clang::​format::​FormattingAttemptStatus *)::​[lambda(clang::​format::​Environment const &) (instance 3)]::​operator ()(clang::​format::​Environment const &): A very large function call parameter exceeding the high threshold is passed by value. (CWE-398)

if (Style.InsertBraces) {
3483 FormatStyle S = Expanded;
3484 S.InsertBraces = true;

pass_by_value: Capturing variable S of type clang::format::FormatStyle (size 572 bytes) by value, which exceeds the high threshold of 512 bytes.

3485 Passes.emplace_back([&, S](const Environment &Env) {
3486 return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
3487 });
3488 }

Can you link to the Coverity issue so we can see what it was complaining about?

Unfortunately this is from an internal-run of Coverity that Intel is running. I'd be shocked if it doesn't appear on the open-source/LLVM version though?

ok! I'm not a massive lambda expert, but aren't we passing by const reference e.g. const FormatStyle &Style, can someone give me a lession as to why it thinks its by value? maybe I'm looking at the wrong "pass by"

MyDeveloperDay added inline comments.May 3 2023, 11:19 AM
clang/lib/Format/Format.cpp
3486–3489

Apart from perhaps the unnecessary copying from Expanded -> S.. doesn't this bascially do the same without us having to remember to put Expanded back afterwards? I don't see how using Expanded is any different from using S (other than the copy)

if (Style.InsertBraces) {
      FormatStyle S = Expanded;
      S.InsertBraces = true;
      Passes.emplace_back([&](const Environment &Env) {
        return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
      });
    }
clang/lib/Format/Format.cpp
3486–3489

I'm not sure if it's worth the trouble, but if I really had to bother, I would do something like the above.

That wouldn't work, since the pass is only executed afterwards.

3486–3489

Apart from perhaps the unnecessary copying from Expanded -> S.. doesn't this bascially do the same without us having to remember to put Expanded back afterwards? I don't see how using Expanded is any different from using S (other than the copy)

if (Style.InsertBraces) {
      FormatStyle S = Expanded;
      S.InsertBraces = true;
      Passes.emplace_back([&](const Environment &Env) {
        return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
      });
    }

That would have a dangling reference to S and most likely don't work as wished.

3486–3489

This should work. One could replace the two assignments with a RAII wrapper which restores the old value.

tahonermann added inline comments.May 3 2023, 12:25 PM
clang/lib/Format/Format.cpp
3486–3489

Here is another option; it is just the original code but with an init capture that does a move instead of a copy. Coverity shouldn't complain about a move capture (if it does, I'll file a support case with Synopsys).

Manna updated this revision to Diff 519337.May 3 2023, 7:36 PM
Manna retitled this revision from [NFC][Clang]Fix static analyzer tool remarks about large copies by value to [NFC][Clang]Fix static analyzer tool remarks about large copies by values.
Manna edited the summary of this revision. (Show Details)

Thank you for the reviews and feedbacks. I have applied suggestion about init capture that does a move instead of a copy.

owenpan added inline comments.May 3 2023, 9:31 PM
clang/lib/Format/Format.cpp
3486–3489

I'm not sure if it's worth the trouble, but if I really had to bother, I would do something like the above.

That wouldn't work, since the pass is only executed afterwards.

You're right!

3486–3489

Apart from perhaps the unnecessary copying from Expanded -> S.. doesn't this bascially do the same without us having to remember to put Expanded back afterwards? I don't see how using Expanded is any different from using S (other than the copy)

if (Style.InsertBraces) {
      FormatStyle S = Expanded;
      S.InsertBraces = true;
      Passes.emplace_back([&](const Environment &Env) {
        return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
      });
    }

That would have a dangling reference to S and most likely don't work as wished.

+1. See D140058#4000311.

tahonermann accepted this revision.May 5 2023, 2:48 PM

Looks good. Thanks again for catching our oops @HazardyKnusperkeks!

This revision is now accepted and ready to land.May 5 2023, 2:48 PM
Manna added a comment.May 5 2023, 2:58 PM

Thank you everyone for reviews and comments.

Manna added a comment.May 5 2023, 6:28 PM

Thanks again for catching our oops @HazardyKnusperkeks!

Yup, Thank you @HazardyKnusperkeks!