[PATCH] D81583: Update SystemZ ABI to handle C++20 [[no_unique_address]] attribute

Ulrich Weigand via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 8 07:07:28 PDT 2020


uweigand marked 6 inline comments as done.
uweigand added inline comments.


================
Comment at: clang/lib/CodeGen/TargetInfo.cpp:521
+  // [[no_unique_address]] attribute (since C++20).  Those do count
+  // as empty according to the Itanium ABI.  This property is currently
+  // only respected if the AllowNoUniqueAddr parameter is true.
----------------
hubert.reinterpretcast wrote:
> This check is being done after removal of the array types by `AllowArrays`, so this code is also conferring the property of being empty to arrays. It seems GCC erroneously does the same for base class fields (but not for direct members).
> 
> ```
> struct Empty {};
> 
> struct A {
>   Empty emp [[no_unique_address]][3];
> };
> 
> struct B : A {
>   float f;
> };
> 
> struct C {
>   Empty emp [[no_unique_address]][3];
>   float f;
> };
> 
> extern char szb[sizeof(B)];
> extern char szb[sizeof(float)]; // GCC likes this
> extern char szc[sizeof(C)];
> extern char szc[sizeof(float)]; // GCC does not like this
> ```
> 
> Compiler Explorer link: https://godbolt.org/z/NFuca9
This version should fix clang; I agree that GCC still gets this wrong.


================
Comment at: clang/lib/CodeGen/TargetInfo.cpp:524
+  if (isa<CXXRecordDecl>(RT->getDecl()) &&
+      !(AllowNoUniqueAddr && FD->hasAttr<NoUniqueAddressAttr>()))
     return false;
----------------
efriedma wrote:
> Does this do the right thing with a field that's an array of empty classes?
You're right.  As Hubert notes, arrays of empty classes do not count as empty.  This version should fix the problem.  


================
Comment at: clang/lib/CodeGen/TargetInfo.cpp:7245
       // do count.  So do anonymous bitfields that aren't zero-sized.
-      if (getContext().getLangOpts().CPlusPlus &&
-          FD->isZeroLengthBitField(getContext()))
-        continue;
+      if (getContext().getLangOpts().CPlusPlus) {
+        if (FD->isZeroLengthBitField(getContext()))
----------------
efriedma wrote:
> Only loosely relevant to this patch, but checking getLangOpts().CPlusPlus here seems weird; doesn't that break calling functions defined in C from C++ code?
I agree that this difference between C and C++ is weird, but it does match the behavior of GCC.  (Which is itself weird, but a long-standing accident that we probably cannot fix without breaking existing code at this point.)

Now, you bring up an interesting point: When C++ code calls a function defined in C code, the C++ part would have to refer to an `extern "C"` declaration.  The correct thing to do would probably be to handle those according to the C ABI rules, not the C++ rules, in this case where the two differ.  But currently GCC doesn't do that either.  (But since that would be broken anyway, I think we **can** fix that.)  In any case, I agree that this is really a separate problem, distinct from this patch.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D81583/new/

https://reviews.llvm.org/D81583





More information about the cfe-commits mailing list