r350920 - [Sema] Make canPassInRegisters return true if the CXXRecordDecl passed

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 16 06:13:04 PST 2019


On Wed, Jan 16, 2019 at 1:57 AM Akira Hatanaka <ahatanaka at apple.com> wrote:
>
> Yes, the behavior of the compiler doesn’t match what’s explained in the documentation anymore.
>
> Please take a look at the attached patch, which updates the documentation.

Patch mostly LGTM, but I did have one wording suggestion.

> diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
> index 5773a92c9c..ca3cfcf9b2 100644
> --- a/include/clang/Basic/AttrDocs.td
> +++ b/include/clang/Basic/AttrDocs.td
> @@ -2478,15 +2478,20 @@ def TrivialABIDocs : Documentation {
>    let Category = DocCatVariable;
>    let Content = [{
>  The ``trivial_abi`` attribute can be applied to a C++ class, struct, or union.
> -It instructs the compiler to pass and return the type using the C ABI for the
> +``trivial_abi`` has the following effects:
> +
> +- It instructs the compiler to pass and return the type using the C ABI for the
>  underlying type when the type would otherwise be considered non-trivial for the
>  purpose of calls.
> -A class annotated with `trivial_abi` can have non-trivial destructors or copy/move constructors without automatically becoming non-trivial for the purposes of calls. For example:
> +- It makes the destructor and copy and move constructors of the class trivial
> +that would otherwise be considered non-trivial under the C++ ABI rules.

How about: It makes the destructor, copy constructors, and move
constructors of the class trivial even if they would otherwise be
non-trivial under the C++ ABI rules.

~Aaron

> +
> +For example:
>
>    .. code-block:: c++
>
> -    // A is trivial for the purposes of calls because `trivial_abi` makes the
> -    // user-provided special functions trivial.
> +    // A is trivial for the purposes of calls despite having a destructor and
> +    // copy and move constructors that are non-trivial under the C++ ABI rules.
>      struct __attribute__((trivial_abi)) A {
>        ~A();
>        A(const A &);
> @@ -2495,11 +2500,26 @@ A class annotated with `trivial_abi` can have non-trivial destructors or copy/mo
>      };
>
>      // B's destructor and copy/move constructor are considered trivial for the
> -    // purpose of calls because A is trivial.
> +    // purpose of calls because A's destructor and copy and move constructors
> +    // are treated as being trivial.
>      struct B {
>        A a;
>      };
>
> +    // C is trivial for the purposes of calls despite having all of its copy and
> +    // move constructors deleted.
> +    struct __attribute__((trivial_abi)) C {
> +      C(const C &) = delete;
> +      C(C &&) = delete;
> +      int x;
> +    };
> +
> +    // D is non-trivial for the purposes of calls since it isn't annotated with
> +    // trivial_abi and all of its copy and move constructors are deleted.
> +    struct D {
> +      C c;
> +    };
> +
>  If a type is trivial for the purposes of calls, has a non-trivial destructor,
>  and is passed as an argument by value, the convention is that the callee will
>  destroy the object before returning.
>
>
>
>
> CC’ing a couple more people who commented on the original patch.
>
> On Jan 10, 2019, at 11:30 PM, Richard Smith <richard at metafoo.co.uk> wrote:
>
> This is an ABI break (theoretically), but due to its nature I'm not too concerned.
>
> Please update the documentation for the attribute to describe these new semantics, though: the documentation currently says that we're just treating certain special members as if they were trivial when determining whether we can pass in registers, and that's not true any more, because the ABI says that classes with only deleted copy and move ctors is never passed in registers regardless of triviality.
>
> On Thu, 10 Jan 2019, 23:10 Akira Hatanaka via cfe-commits <cfe-commits at lists.llvm.org wrote:
>>
>> Author: ahatanak
>> Date: Thu Jan 10 23:06:38 2019
>> New Revision: 350920
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=350920&view=rev
>> Log:
>> [Sema] Make canPassInRegisters return true if the CXXRecordDecl passed
>> to it is a trivial_abi class.
>>
>> A class that has all of its copy and move constructors deleted can still
>> be passed or returned in registers if the class is annotated with
>> trivial_abi.
>>
>> This fixes PR39683.
>>
>> Modified:
>>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>>     cfe/trunk/test/CodeGenCXX/trivial_abi.cpp
>>
>> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=350920&r1=350919&r2=350920&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jan 10 23:06:38 2019
>> @@ -5886,6 +5886,9 @@ static bool canPassInRegisters(Sema &S,
>>    if (D->isDependentType() || D->isInvalidDecl())
>>      return false;
>>
>> +  if (D->hasAttr<TrivialABIAttr>())
>> +    return true;
>> +
>>    // Clang <= 4 used the pre-C++11 rule, which ignores move operations.
>>    // The PS4 platform ABI follows the behavior of Clang 3.2.
>>    if (CCK == TargetInfo::CCK_ClangABI4OrPS4)
>>
>> Modified: cfe/trunk/test/CodeGenCXX/trivial_abi.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/trivial_abi.cpp?rev=350920&r1=350919&r2=350920&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/trivial_abi.cpp (original)
>> +++ cfe/trunk/test/CodeGenCXX/trivial_abi.cpp Thu Jan 10 23:06:38 2019
>> @@ -1,5 +1,5 @@
>> -// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
>> -// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
>> +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
>> +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
>>
>>  // CHECK: %[[STRUCT_SMALL:.*]] = type { i32* }
>>  // CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] }
>> @@ -43,6 +43,13 @@ struct HasNonTrivial {
>>    NonTrivial m;
>>  };
>>
>> +struct __attribute__((trivial_abi)) CopyMoveDeleted {
>> +  CopyMoveDeleted(int);
>> +  CopyMoveDeleted(const CopyMoveDeleted &) = delete;
>> +  CopyMoveDeleted(CopyMoveDeleted &&) = delete;
>> +  int a;
>> +};
>> +
>>  // CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]])
>>  // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8
>>  // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0
>> @@ -237,3 +244,11 @@ void calleeExceptionLarge(Large, Large);
>>  void testExceptionLarge() {
>>    calleeExceptionLarge(Large(), Large());
>>  }
>> +
>> +// A class with deleted copy and move constructors can still be passed or
>> +// returned in registers if the class is annotated with trivial_abi.
>> +
>> +// CHECK: define i64 @_Z19testCopyMoveDeletedi(i32 %
>> +CopyMoveDeleted testCopyMoveDeleted(int a) {
>> +  return a;
>> +}
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
>


More information about the cfe-commits mailing list