Author: Amirreza Ashouri
Date: 2024-03-11T04:23:23+01:00
New Revision: 7dfa8398354e435cdee5a8ea6d6b17d1e4557733

URL: 
https://github.com/llvm/llvm-project/commit/7dfa8398354e435cdee5a8ea6d6b17d1e4557733
DIFF: 
https://github.com/llvm/llvm-project/commit/7dfa8398354e435cdee5a8ea6d6b17d1e4557733.diff

LOG: [clang] Fix behavior of `__is_trivially_relocatable(volatile int)` (#77092)

Consistent with `__is_trivially_copyable(volatile int) == true` and
`__is_trivially_relocatable(volatile Trivial) == true`,
`__is_trivially_relocatable(volatile int)` should also be `true`.

Fixes https://github.com/llvm/llvm-project/issues/77091

[clang] [test] New tests for __is_trivially_relocatable(cv-qualified
type)

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/Type.cpp
    clang/test/SemaCXX/type-traits.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3b89d5a8720785..bce27dc8c4a996 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -251,6 +251,9 @@ Bug Fixes in This Version
   for logical operators in C23.
   Fixes (#GH64356).
 
+- ``__is_trivially_relocatable`` no longer returns ``false`` for 
volatile-qualified types.
+  Fixes (#GH77091).
+
 - Clang no longer produces a false-positive `-Wunused-variable` warning
   for variables created through copy initialization having side-effects in 
C++17 and later.
   Fixes (#GH64356) (#GH79518).

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 78dcd3f4007a5a..22666184c56ccf 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2682,6 +2682,8 @@ bool QualType::isTriviallyRelocatableType(const 
ASTContext &Context) const {
     return false;
   } else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
     return RD->canPassInRegisters();
+  } else if (BaseElementType.isTriviallyCopyableType(Context)) {
+    return true;
   } else {
     switch (isNonTrivialToPrimitiveDestructiveMove()) {
     case PCK_Trivial:

diff  --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index f50f51cc70982e..14ec17989ec7c7 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1722,91 +1722,91 @@ struct StructWithAnonUnion3 {
 
 void is_layout_compatible(int n)
 {
-  static_assert(__is_layout_compatible(void, void), "");
-  static_assert(!__is_layout_compatible(void, int), "");
-  static_assert(__is_layout_compatible(void, const void), "");
-  static_assert(__is_layout_compatible(void, volatile void), "");
-  static_assert(__is_layout_compatible(const int, volatile int), "");
-  static_assert(__is_layout_compatible(int, int), "");
-  static_assert(__is_layout_compatible(int, const int), "");
-  static_assert(__is_layout_compatible(int, volatile int), "");
-  static_assert(__is_layout_compatible(const int, volatile int), "");
-  static_assert(__is_layout_compatible(int *, int * __restrict), "");
+  static_assert(__is_layout_compatible(void, void));
+  static_assert(!__is_layout_compatible(void, int));
+  static_assert(__is_layout_compatible(void, const void));
+  static_assert(__is_layout_compatible(void, volatile void));
+  static_assert(__is_layout_compatible(const int, volatile int));
+  static_assert(__is_layout_compatible(int, int));
+  static_assert(__is_layout_compatible(int, const int));
+  static_assert(__is_layout_compatible(int, volatile int));
+  static_assert(__is_layout_compatible(const int, volatile int));
+  static_assert(__is_layout_compatible(int *, int * __restrict));
   // Note: atomic qualification matters for layout compatibility.
-  static_assert(!__is_layout_compatible(int, _Atomic int), "");
-  static_assert(__is_layout_compatible(_Atomic(int), _Atomic int), "");
-  static_assert(!__is_layout_compatible(int, unsigned int), "");
-  static_assert(!__is_layout_compatible(char, unsigned char), "");
-  static_assert(!__is_layout_compatible(char, signed char), "");
-  static_assert(!__is_layout_compatible(unsigned char, signed char), "");
-  static_assert(__is_layout_compatible(int[], int[]), "");
-  static_assert(__is_layout_compatible(int[2], int[2]), "");
-  static_assert(!__is_layout_compatible(int[n], int[2]), ""); // FIXME: VLAs 
should be rejected
-  static_assert(!__is_layout_compatible(int[n], int[n]), ""); // FIXME: VLAs 
should be rejected
-  static_assert(__is_layout_compatible(int&, int&), "");
-  static_assert(!__is_layout_compatible(int&, char&), "");
-  static_assert(__is_layout_compatible(void(int), void(int)), "");
-  static_assert(!__is_layout_compatible(void(int), void(char)), "");
-  static_assert(__is_layout_compatible(void(&)(int), void(&)(int)), "");
-  static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)), "");
-  static_assert(__is_layout_compatible(void(*)(int), void(*)(int)), "");
-  static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)), "");
+  static_assert(!__is_layout_compatible(int, _Atomic int));
+  static_assert(__is_layout_compatible(_Atomic(int), _Atomic int));
+  static_assert(!__is_layout_compatible(int, unsigned int));
+  static_assert(!__is_layout_compatible(char, unsigned char));
+  static_assert(!__is_layout_compatible(char, signed char));
+  static_assert(!__is_layout_compatible(unsigned char, signed char));
+  static_assert(__is_layout_compatible(int[], int[]));
+  static_assert(__is_layout_compatible(int[2], int[2]));
+  static_assert(!__is_layout_compatible(int[n], int[2])); // FIXME: VLAs 
should be rejected
+  static_assert(!__is_layout_compatible(int[n], int[n])); // FIXME: VLAs 
should be rejected
+  static_assert(__is_layout_compatible(int&, int&));
+  static_assert(!__is_layout_compatible(int&, char&));
+  static_assert(__is_layout_compatible(void(int), void(int)));
+  static_assert(!__is_layout_compatible(void(int), void(char)));
+  static_assert(__is_layout_compatible(void(&)(int), void(&)(int)));
+  static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)));
+  static_assert(__is_layout_compatible(void(*)(int), void(*)(int)));
+  static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)));
   using function_type = void();
   using function_type2 = void(char);
-  static_assert(__is_layout_compatible(const function_type, const 
function_type), "");
+  static_assert(__is_layout_compatible(const function_type, const 
function_type));
   // expected-warning@-1 {{'const' qualifier on function type 'function_type' 
(aka 'void ()') has no effect}}
   // expected-warning@-2 {{'const' qualifier on function type 'function_type' 
(aka 'void ()') has no effect}}
-  static_assert(__is_layout_compatible(function_type, const function_type), 
"");
+  static_assert(__is_layout_compatible(function_type, const function_type));
   // expected-warning@-1 {{'const' qualifier on function type 'function_type' 
(aka 'void ()') has no effect}}
-  static_assert(!__is_layout_compatible(const function_type, const 
function_type2), "");
+  static_assert(!__is_layout_compatible(const function_type, const 
function_type2));
   // expected-warning@-1 {{'const' qualifier on function type 'function_type' 
(aka 'void ()') has no effect}}
   // expected-warning@-2 {{'const' qualifier on function type 'function_type2' 
(aka 'void (char)') has no effect}}
-  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
-  static_assert(__is_layout_compatible(CStruct, const CStruct2), "");
-  static_assert(__is_layout_compatible(CStruct, volatile CStruct2), "");
-  static_assert(__is_layout_compatible(const CStruct, volatile CStruct2), "");
-  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
-  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
-  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), 
"");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, 
CppStructNonStandardByVirtBase2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, 
CppStructNonStandardBySameBase2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, 
CppStructNonStandardBy2ndVirtBase2), "");
-  static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), "");
-  static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != 
bool(__has_cpp_attribute(no_unique_address)), "");
-  static_assert(__is_layout_compatible(CStructNoUniqueAddress, 
CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), "");
-  static_assert(__is_layout_compatible(CStruct, CStructAlignment), "");
-  static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers), "");
-  static_assert(__is_layout_compatible(UnionNoOveralignedMembers, 
UnionWithOveralignedMembers), "");
-  static_assert(__is_layout_compatible(CStructWithBitfelds, 
CStructWithBitfelds), "");
-  static_assert(__is_layout_compatible(CStructWithBitfelds, 
CStructWithBitfelds2), "");
-  static_assert(!__is_layout_compatible(CStructWithBitfelds, 
CStructWithBitfelds3), "");
-  static_assert(!__is_layout_compatible(CStructWithBitfelds, 
CStructWithBitfelds4), "");
-  static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*), "");
-  static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*), 
"");
-  static_assert(__is_layout_compatible(void(CStruct2::*)(int), 
void(CStruct2::*)(int)), "");
-  static_assert(!__is_layout_compatible(void(CStruct2::*)(int), 
void(CStruct2::*)(char)), "");
-  static_assert(__is_layout_compatible(CStructNested, CStructNested2), "");
-  static_assert(__is_layout_compatible(UnionLayout, UnionLayout), "");
-  static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), "");
-  static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), "");
-  static_assert(!__is_layout_compatible(StructWithAnonUnion, 
StructWithAnonUnion2), "");
-  static_assert(!__is_layout_compatible(StructWithAnonUnion, 
StructWithAnonUnion3), "");
-  static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout), "");
-  static_assert(__is_layout_compatible(EnumForward, EnumForward), "");
-  static_assert(__is_layout_compatible(EnumForward, EnumClassForward), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2));
+  static_assert(__is_layout_compatible(CStruct, const CStruct2));
+  static_assert(__is_layout_compatible(CStruct, volatile CStruct2));
+  static_assert(__is_layout_compatible(const CStruct, volatile CStruct2));
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2));
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2));
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, 
CppStructNonStandardByVirtBase2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, 
CppStructNonStandardBySameBase2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, 
CppStructNonStandardBy2ndVirtBase2));
+  static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers));
+  static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != 
bool(__has_cpp_attribute(no_unique_address)));
+  static_assert(__is_layout_compatible(CStructNoUniqueAddress, 
CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)));
+  static_assert(__is_layout_compatible(CStruct, CStructAlignment));
+  static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers));
+  static_assert(__is_layout_compatible(UnionNoOveralignedMembers, 
UnionWithOveralignedMembers));
+  static_assert(__is_layout_compatible(CStructWithBitfelds, 
CStructWithBitfelds));
+  static_assert(__is_layout_compatible(CStructWithBitfelds, 
CStructWithBitfelds2));
+  static_assert(!__is_layout_compatible(CStructWithBitfelds, 
CStructWithBitfelds3));
+  static_assert(!__is_layout_compatible(CStructWithBitfelds, 
CStructWithBitfelds4));
+  static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*));
+  static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*));
+  static_assert(__is_layout_compatible(void(CStruct2::*)(int), 
void(CStruct2::*)(int)));
+  static_assert(!__is_layout_compatible(void(CStruct2::*)(int), 
void(CStruct2::*)(char)));
+  static_assert(__is_layout_compatible(CStructNested, CStructNested2));
+  static_assert(__is_layout_compatible(UnionLayout, UnionLayout));
+  static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2));
+  static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3));
+  static_assert(!__is_layout_compatible(StructWithAnonUnion, 
StructWithAnonUnion2));
+  static_assert(!__is_layout_compatible(StructWithAnonUnion, 
StructWithAnonUnion3));
+  static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout));
+  static_assert(__is_layout_compatible(EnumForward, EnumForward));
+  static_assert(__is_layout_compatible(EnumForward, EnumClassForward));
   // Layout compatibility for enums might be relaxed in the future. See 
https://github.com/cplusplus/CWG/issues/39#issuecomment-1184791364
-  static_assert(!__is_layout_compatible(EnumLayout, int), "");
-  static_assert(!__is_layout_compatible(EnumClassLayout, int), "");
-  static_assert(!__is_layout_compatible(EnumForward, int), "");
-  static_assert(!__is_layout_compatible(EnumClassForward, int), "");
+  static_assert(!__is_layout_compatible(EnumLayout, int));
+  static_assert(!__is_layout_compatible(EnumClassLayout, int));
+  static_assert(!__is_layout_compatible(EnumForward, int));
+  static_assert(!__is_layout_compatible(EnumClassForward, int));
   // FIXME: the following should be rejected (array of unknown bound and void 
are the only allowed incomplete types)
-  static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete), 
""); 
-  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
-  static_assert(__is_layout_compatible(CStructIncomplete[2], 
CStructIncomplete[2]), "");
+  static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete)); 
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete));
+  static_assert(__is_layout_compatible(CStructIncomplete[2], 
CStructIncomplete[2]));
 }
 
 void is_signed()
@@ -3340,6 +3340,8 @@ namespace is_trivially_relocatable {
 static_assert(!__is_trivially_relocatable(void));
 static_assert(__is_trivially_relocatable(int));
 static_assert(__is_trivially_relocatable(int[]));
+static_assert(__is_trivially_relocatable(const int));
+static_assert(__is_trivially_relocatable(volatile int));
 
 enum Enum {};
 static_assert(__is_trivially_relocatable(Enum));
@@ -3351,7 +3353,28 @@ static_assert(__is_trivially_relocatable(Union[]));
 
 struct Trivial {};
 static_assert(__is_trivially_relocatable(Trivial));
+static_assert(__is_trivially_relocatable(const Trivial));
+static_assert(__is_trivially_relocatable(volatile Trivial));
+
 static_assert(__is_trivially_relocatable(Trivial[]));
+static_assert(__is_trivially_relocatable(const Trivial[]));
+static_assert(__is_trivially_relocatable(volatile Trivial[]));
+
+static_assert(__is_trivially_relocatable(int[10]));
+static_assert(__is_trivially_relocatable(const int[10]));
+static_assert(__is_trivially_relocatable(volatile int[10]));
+
+static_assert(__is_trivially_relocatable(int[10][10]));
+static_assert(__is_trivially_relocatable(const int[10][10]));
+static_assert(__is_trivially_relocatable(volatile int[10][10]));
+
+static_assert(__is_trivially_relocatable(int[]));
+static_assert(__is_trivially_relocatable(const int[]));
+static_assert(__is_trivially_relocatable(volatile int[]));
+
+static_assert(__is_trivially_relocatable(int[][10]));
+static_assert(__is_trivially_relocatable(const int[][10]));
+static_assert(__is_trivially_relocatable(volatile int[][10]));
 
 struct Incomplete; // expected-note {{forward declaration of 
'is_trivially_relocatable::Incomplete'}}
 bool unused = __is_trivially_relocatable(Incomplete); // expected-error 
{{incomplete type}}
@@ -3361,6 +3384,8 @@ struct NontrivialDtor {
 };
 static_assert(!__is_trivially_relocatable(NontrivialDtor));
 static_assert(!__is_trivially_relocatable(NontrivialDtor[]));
+static_assert(!__is_trivially_relocatable(const NontrivialDtor));
+static_assert(!__is_trivially_relocatable(volatile NontrivialDtor));
 
 struct NontrivialCopyCtor {
   NontrivialCopyCtor(const NontrivialCopyCtor&) {}
@@ -3379,12 +3404,16 @@ struct [[clang::trivial_abi]] TrivialAbiNontrivialDtor {
 };
 static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor));
 static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor[]));
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialDtor));
+static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialDtor));
 
 struct [[clang::trivial_abi]] TrivialAbiNontrivialCopyCtor {
   TrivialAbiNontrivialCopyCtor(const TrivialAbiNontrivialCopyCtor&) {}
 };
 static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor));
 static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor[]));
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialCopyCtor));
+static_assert(__is_trivially_relocatable(volatile 
TrivialAbiNontrivialCopyCtor));
 
 // A more complete set of tests for the behavior of trivial_abi can be found in
 // clang/test/SemaCXX/attr-trivial-abi.cpp
@@ -3393,6 +3422,8 @@ struct [[clang::trivial_abi]] 
TrivialAbiNontrivialMoveCtor {
 };
 static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor));
 static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor[]));
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialMoveCtor));
+static_assert(__is_trivially_relocatable(volatile 
TrivialAbiNontrivialMoveCtor));
 
 } // namespace is_trivially_relocatable
 


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to