This is an archive of the discontinued LLVM Phabricator instance.

[NFC][clang] Fix static analyzer concerns about AUTO_CAUSES_COPY
ClosedPublic

Authored by Manna on Apr 18 2023, 8:20 AM.

Details

Summary

Reported by Coverity:

AUTO_CAUSES_COPY
Unnecessary object copies can affect performance

  1. Inside "ODRHash.cpp" file, in clang::​ODRHash::​AddCXXRecordDecl(clang::​CXXRecordDecl const *): Using the auto keyword without an & causes the copy of an object of type CXXBaseSpecifier.
  1. Inside "Tokens.cpp" file, in clang::​syntax::​TokenBuffer::​dumpForTests[abi:cxx11](): Using the auto keyword without an & causes the copy of an object of type DenseMapPair.
  1. Inside "TargetID.cpp" file, in clang::​getCanonicalTargetID[abi:cxx11](llvm::​StringRef, llvm::​StringMap<bool, llvm::​MallocAllocator> const &): Using the auto keyword without an & causes the copy of an object of type pair.

Diff Detail

Event Timeline

Manna created this revision.Apr 18 2023, 8:20 AM
Herald added a project: Restricted Project. · View Herald Transcript
Manna requested review of this revision.Apr 18 2023, 8:20 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 18 2023, 8:20 AM

Thanks for the static analysis fixes, however, it looks like quite a few of them were false positives again. When fixing any static analysis diagnostics, please put in the effort to determine whether it's actually correct or not, as it seem the Coverity diagnostic is not really paying any attention to the size of what's being copied. If you're applying the advice from the tool without further analysis, it can be disruptive (might introduce bugs, churns the code for negative/no benefit, lowers reviewer confidence in the rest of the changes, etc). (Not suggesting you're blindly applying advice, but mostly observing we've had a few reviews like this.)

My suggestion is to always look at the size of what's being copied. As a general rule of thumb, if it's two pointers or less in size, the copy is likely cheaper than the reference and shouldn't be changed.

clang/lib/AST/ExprConstant.cpp
6117 ↗(On Diff #514643)

This returns a ParamIdx object which is 32-bits, so it's not expensive to copy.

clang/lib/Basic/TargetID.cpp
136

The map iterator returns a std::pair<StringRef, bool> which is not particularly expensive to copy, but I think this is borderline enough that it's fine to keep.

clang/lib/Basic/Targets/ARM.cpp
463 ↗(On Diff #514643)

This returns a StringRef which is not expensive to copy.

clang/lib/CodeGen/CGExpr.cpp
3548 ↗(On Diff #514643)

This is a pair of ints, not expensive to copy.

clang/lib/Serialization/ASTReader.cpp
9426 ↗(On Diff #514643)

Why is the above considered too expensive but this one is not?

clang/lib/Tooling/Syntax/Tokens.cpp
989

FileID is an int, not expensive to copy.

After seeing this review, I filed a support case with Synopsys with a request to stop reporting AUTO_CAUSES_COPY issues for small objects of class types, at least in the absence of additional evidence that a reference would be preferred.

clang/lib/AST/ODRHash.cpp
597

This seems like a good change; CXXBaseSpecifier isn't particularly large, but this seems like a case where reference semantics are more intuitive anyway.

clang/lib/Serialization/ASTReader.cpp
9426 ↗(On Diff #514643)

I'm guessing that Coverity reported it as a second occurrence and those are easy to overlook.

clang/lib/Tooling/Syntax/Tokens.cpp
989

Files has type llvm::DenseMap<FileID, MarkedFile>, so the element type is DenseMapPair<FileID, MarkedFile>. MarkedFile contains a couple of vectors, so this looks like a win to me.

steakhal added inline comments.Apr 19 2023, 5:36 AM
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
1053 ↗(On Diff #514643)

I think this is supposed to be just some lightweight handle: some discriminator and pointer under the hood. sizeof(I)
is just 40 bytes. Another point is that the copy construction is not customized, so the sizeof for such objects should be a good proxy for estimating how costly the copy is.

For me personally, if it fits into a cacheline (on x86_64 I think its 64 bytes) (and ~trivially-copyable) then it should've probably taken by value.
I haven't measured this theory, so take it with a pinch of salt.

Manna updated this revision to Diff 515318.Apr 20 2023, 7:14 AM

Thank you everyone for reviews and feedbacks. I misunderstood some of the False positive Coverity cases. Thanks for the explanation and suggestions. I will keep this in mind while investigating static analysis in future. This patch removes FP cases.

Manna edited the summary of this revision. (Show Details)Apr 20 2023, 7:15 AM
Manna marked 7 inline comments as done.Apr 20 2023, 7:21 AM
Manna added inline comments.
clang/lib/Serialization/ASTReader.cpp
9426 ↗(On Diff #514643)

Yes, i missed this case. I will investigate it further, so this case has been removed from the current patch.

clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
1053 ↗(On Diff #514643)

Thanks for the explanation!

tahonermann accepted this revision.Apr 20 2023, 10:14 AM

This set of changes looks good to me.

This revision is now accepted and ready to land.Apr 20 2023, 10:14 AM
Manna marked an inline comment as done.Apr 21 2023, 5:56 AM

@aaron.ballman, do you have any more concerns or comments? Thank you

Manna added a comment.Apr 23 2023, 3:31 PM

This set of changes looks good to me.

Thank you @tahonermann