This is an archive of the discontinued LLVM Phabricator instance.

[NFC][Clang][Coverity] Fix Static Code Analysis Concerns with copy without assign
ClosedPublic

Authored by Manna on May 11 2023, 6:35 PM.

Details

Summary

This patch adds missing assignment operator to the class which has user-defined copy/move constructor.

Diff Detail

Event Timeline

Manna created this revision.May 11 2023, 6:35 PM
Herald added a project: Restricted Project. · View Herald Transcript
Manna requested review of this revision.May 11 2023, 6:35 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 11 2023, 6:35 PM
Manna abandoned this revision.EditedMay 11 2023, 6:37 PM
This comment has been deleted.
Manna updated this revision to Diff 521529.May 11 2023, 7:01 PM
Manna retitled this revision from [NFC][Clang] Fix Static Code Analysis Concerns to [NFC][Clang][Coverity] Fix Static Code Analysis Concerns with copy without assign.May 11 2023, 7:08 PM
Manna added inline comments.May 11 2023, 7:37 PM
clang/include/clang/Sema/Sema.h
1789–1791

@tahonermann This is follow-up comments from https://reviews.llvm.org/D149718?id=519331#inline-1452044.

This change still declares a move assignment operator, but doesn't provide a definition. The move constructor is implemented in clang/lib/Sema/Sema.cpp, so I would expect to see the move assignment operator definition provided there as well.

I tried to define move assignment operator in clang/lib/Sema/Sema.cpp but it failed because class Sema has deleted implicit copy assignment operator.

/// Sema - This implements semantic analysis and AST building for C.
class Sema final {
  Sema(const Sema &) = delete;
  void operator=(const Sema &) = delete;

It seems like support for assignment is not desired, We probably need deleted copy/move assignment operator.

In several cases it's not completely obvious to me whether a copy assignment operator should or can be defined. But perhaps this doesn't need to be addressed right now: we seem to compile with -Wextra, which contains -Wdeprecated-copy. That should warn if a compiler-generated copy operation is used while another is user-declared.

clang/include/clang/AST/ASTContext.h
3212–3214

Why not just remove both? It seems to me the copy constructor doesn't behave different than the compiler-generated version.

clang/include/clang/Analysis/Analyses/Consumed.h
158–163

The copy constructor doesn't copy TmpMap, which means it's going to be empty afterwards, but if you leave it as-is on assignment, it keeps the previous value, which might be inconsistent with the newly assigned values to the other members. Perhaps the assignment operator should just be deleted?

clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
243–246

I'd hope this is unused, also it probably doesn't do the right thing with NumRefs. Note that the copy constructor will initialize it with 1 due to the in-class initializer, while this is just going to keep the original value.

clang/include/clang/Analysis/Support/BumpVector.h
45–50

There should be no need to define this: declaring a move constructor should delete all other copy/move operations unless also explicitly declared, so this can't currently be used.

clang/include/clang/Sema/Lookup.h
660–661

These should also be implicitly deleted because of the user-declared move constructor.

clang/include/clang/Sema/Sema.h
1789–1791

These are also implicitly deleted. Some code styles want this explicitly spelled out, but I don't think ours does.

clang/lib/Sema/SemaAccess.cpp
203–207

Should this not set S.Target = nullptr like the move constructor? But perhaps this is also just unneeded.

Manna updated this revision to Diff 522608.May 16 2023, 7:26 AM

Thank you @aaronpuchert for reviews and the comments.

Manna marked 6 inline comments as done.May 16 2023, 7:29 AM
tahonermann requested changes to this revision.May 16 2023, 2:48 PM

I added a few comments and suggested edits, but this is mostly looking good.

clang/include/clang/Sema/Sema.h
1789–1791

I tried to define move assignment operator in clang/lib/Sema/Sema.cpp but it failed because class Sema has deleted implicit copy assignment operator.

It is still permissible to define a move assignment operator if the implicit copy assignment operator is deleted. See https://godbolt.org/z/sGaWd9M44.

I think it is fine to disable support for assignment for this class pending use cases. But, since a move constructor is explicitly defined, we should also be explicit above move assignment. I added a suggested edit. Without that change, I think Coverity will continue to complain.

1790
clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
54

Here too; since a user-defined move constructor is declared, let's be explicit about move assignment.

clang/lib/CodeGen/CGDebugInfo.h
833–837

Good catch! Since the destructor uses CGF, the defaulted move assignment operator was wrong!

clang/lib/CodeGen/EHScopeStack.h
151

Here too; since a user-declared move constructor is present, let's be explicit about support for move assignment.

This revision now requires changes to proceed.May 16 2023, 2:48 PM
Manna updated this revision to Diff 522821.May 16 2023, 3:51 PM
Manna marked 3 inline comments as done.

Thanks @tahonermann for your reviews and feedbacks. I have addressed your review comments.

clang/include/clang/Sema/Sema.h
1789–1791

I see! Thanks @tahonermann for the explanation

I'd probably abstain from explicitly deleting what is already implicitly deleted, but otherwise this looks good to me. Thanks!

clang/include/clang/Sema/Sema.h
1790

Being explicit is certainly a good thing, but the C++ committee wants to go into the direction of "copy/move operations are implicitly deleted if any of them or the destructor is user-declared." See depr.impldec. It is already partially the case, for example here. So why do need to spell something out explicitly when the language goes into the direction of being even more implicit?

Manna updated this revision to Diff 522826.May 16 2023, 4:06 PM
tahonermann added inline comments.May 17 2023, 7:13 PM
clang/include/clang/Sema/Sema.h
1790

I have low expectations of that deprecation ever being acted on. In fact, there have been discussions about un-deprecating it because of the lack of such intent.

The motivation for deprecation is not based on a judgement of whether implicit or explicit is better, but rather based on a safety argument; if a copy constructor or destructor is user-declared, that is probably because some form of resource management is needed that won't be performed by the defaulted copy assignment operator. Thus, defining the implicit copy assignment operator as deleted would avoid the possibility of the compiler injecting bugs in the program.

The rules for when the copy vs assignment operators are implicitly defined as deleted can be hard to remember. I think being explicit is useful if only to indicate that the author thought about whether such operations should be provided. Since we don't have a principled reason for defining these operations as deleted, it might not be a bad idea to add a comment that states something like "The copy/move assignment operator is defined as deleted pending further motivation".

Manna updated this revision to Diff 523376.May 18 2023, 7:40 AM
Manna added inline comments.May 18 2023, 7:47 AM
clang/include/clang/Sema/Sema.h
1790

Thank you @tahonermann for the comments and the updates about the deprecations discussion.

t might not be a bad idea to add a comment that states something like "The copy/move assignment operator is defined as deleted pending further motivation".

I like the idea of adding a comment since pending standard decision. I have updated my patch with the comments

Manna updated this revision to Diff 523396.May 18 2023, 8:46 AM

Fix clang-format issues

NoQ added a comment.May 18 2023, 12:50 PM

Static Analyzer changes look great, thanks!

Static Analyzer changes look great, thanks!

Thank you @NoQ for reviews!

One last minor request and then I'm happy with this.

clang/include/clang/Sema/ParsedAttr.h
708–710

Let's explicitly delete the copy assignment operator too since the copy constructor is deleted.

Manna updated this revision to Diff 523540.May 18 2023, 1:38 PM
Manna marked an inline comment as done.
Manna added inline comments.May 18 2023, 1:41 PM
clang/include/clang/Sema/ParsedAttr.h
708–710

@tahonermann , copy assignment operator has already been explicitly deleted at line no 701. I made this change part of https://reviews.llvm.org/D149718. It was a rebase issue, so it did show it before with my previous patch. I have fixed it now and added comment since the copy assignment was added explicitly as deleted.

tahonermann accepted this revision.May 18 2023, 2:34 PM

Thanks @Manna, this looks good to me now!

clang/include/clang/Sema/ParsedAttr.h
708–710

Ah, perfect!

This revision is now accepted and ready to land.May 18 2023, 2:34 PM

(& I realize I'm a bit late to the party, but:

In several cases it's not completely obvious to me whether a copy assignment operator should or can be defined. But perhaps this doesn't need to be addressed right now: we seem to compile with -Wextra, which contains -Wdeprecated-copy. That should warn if a compiler-generated copy operation is used while another is user-declared.

The rules for when the copy vs assignment operators are implicitly defined as deleted can be hard to remember. I think being explicit is useful if only to indicate that the author thought about whether such operations should be provided. Since we don't have a principled reason for defining these operations as deleted, it might not be a bad idea to add a comment that states something like "The copy/move assignment operator is defined as deleted pending further motivation".

I'd also vote in favor of the "let it be implicitly deleted - we have the warnings enabled to catch it". But don't feel strongly enough to argue that chunks of this patch should be reverted)

clang/lib/Sema/SemaAccess.cpp
207