Skip to content

Commit fd2ffc1

Browse files
authored
[clang] Reject incomplete types in __is_layout_compatible() (#87869)
This is a follow-up to #81506. As discussed in #87737, we're rejecting incomplete types, save for exceptions listed in the C++ standard (`void` and arrays of unknown bound). Note that arrays of unknown bound of incomplete types are accepted. Since we're happy with the current behavior of this intrinsic for flexible array members (#87737 (comment)), I added a couple of tests for that as well.
1 parent 125c9cf commit fd2ffc1

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6025,6 +6025,11 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
60256025
return false;
60266026
}
60276027
case BTT_IsLayoutCompatible: {
6028+
if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType())
6029+
Self.RequireCompleteType(KeyLoc, LhsT, diag::err_incomplete_type);
6030+
if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType())
6031+
Self.RequireCompleteType(KeyLoc, RhsT, diag::err_incomplete_type);
6032+
60286033
if (LhsT->isVariableArrayType() || RhsT->isVariableArrayType())
60296034
Self.Diag(KeyLoc, diag::err_vla_unsupported)
60306035
<< 1 << tok::kw___is_layout_compatible;

clang/test/SemaCXX/type-traits.cpp

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,7 +1622,7 @@ enum class EnumClassLayout {};
16221622
enum EnumForward : int;
16231623
enum class EnumClassForward;
16241624

1625-
struct CStructIncomplete;
1625+
struct CStructIncomplete; // #CStructIncomplete
16261626

16271627
struct CStructNested {
16281628
int a;
@@ -1719,6 +1719,20 @@ struct StructWithAnonUnion3 {
17191719
} u;
17201720
};
17211721

1722+
struct CStructWithArrayAtTheEnd {
1723+
int a;
1724+
int b[4];
1725+
};
1726+
1727+
struct CStructWithFMA {
1728+
int c;
1729+
int d[];
1730+
};
1731+
1732+
struct CStructWithFMA2 {
1733+
int e;
1734+
int f[];
1735+
};
17221736

17231737
void is_layout_compatible(int n)
17241738
{
@@ -1800,15 +1814,28 @@ void is_layout_compatible(int n)
18001814
static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout));
18011815
static_assert(__is_layout_compatible(EnumForward, EnumForward));
18021816
static_assert(__is_layout_compatible(EnumForward, EnumClassForward));
1803-
// Layout compatibility for enums might be relaxed in the future. See https://github.com/cplusplus/CWG/issues/39#issuecomment-1184791364
1817+
static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete));
1818+
// expected-error@-1 {{incomplete type 'CStructIncomplete' where a complete type is required}}
1819+
// expected-note@#CStructIncomplete {{forward declaration of 'CStructIncomplete'}}
1820+
// expected-error@-3 {{incomplete type 'CStructIncomplete' where a complete type is required}}
1821+
// expected-note@#CStructIncomplete {{forward declaration of 'CStructIncomplete'}}
1822+
static_assert(!__is_layout_compatible(CStruct, CStructIncomplete));
1823+
// expected-error@-1 {{incomplete type 'CStructIncomplete' where a complete type is required}}
1824+
// expected-note@#CStructIncomplete {{forward declaration of 'CStructIncomplete'}}
1825+
static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]));
1826+
// expected-error@-1 {{incomplete type 'CStructIncomplete[2]' where a complete type is required}}
1827+
// expected-note@#CStructIncomplete {{forward declaration of 'CStructIncomplete'}}
1828+
// expected-error@-3 {{incomplete type 'CStructIncomplete[2]' where a complete type is required}}
1829+
// expected-note@#CStructIncomplete {{forward declaration of 'CStructIncomplete'}}
1830+
static_assert(__is_layout_compatible(CStructIncomplete[], CStructIncomplete[]));
1831+
static_assert(!__is_layout_compatible(CStructWithArrayAtTheEnd, CStructWithFMA));
1832+
static_assert(__is_layout_compatible(CStructWithFMA, CStructWithFMA));
1833+
static_assert(__is_layout_compatible(CStructWithFMA, CStructWithFMA2));
1834+
// Layout compatibility rules for enums might be relaxed in the future. See https://github.com/cplusplus/CWG/issues/39#issuecomment-1184791364
18041835
static_assert(!__is_layout_compatible(EnumLayout, int));
18051836
static_assert(!__is_layout_compatible(EnumClassLayout, int));
18061837
static_assert(!__is_layout_compatible(EnumForward, int));
18071838
static_assert(!__is_layout_compatible(EnumClassForward, int));
1808-
// FIXME: the following should be rejected (array of unknown bound and void are the only allowed incomplete types)
1809-
static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete));
1810-
static_assert(!__is_layout_compatible(CStruct, CStructIncomplete));
1811-
static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]));
18121839
}
18131840

18141841
void is_signed()

0 commit comments

Comments
 (0)