This patch adds missing assignment operator to the class which has user-defined copy/move constructor.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
clang/include/clang/Sema/Sema.h | ||
---|---|---|
1789–1791 | @tahonermann This is follow-up comments from https://reviews.llvm.org/D149718?id=519331#inline-1452044.
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. |
I added a few comments and suggested edits, but this is mostly looking good.
clang/include/clang/Sema/Sema.h | ||
---|---|---|
1789–1791 |
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. |
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? |
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". |
clang/include/clang/Sema/Sema.h | ||
---|---|---|
1790 | Thank you @tahonermann for the comments and the updates about the deprecations discussion.
I like the idea of adding a comment since pending standard decision. I have updated my patch with the comments |
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. |
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. |
(& 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 |
Why not just remove both? It seems to me the copy constructor doesn't behave different than the compiler-generated version.