-
Notifications
You must be signed in to change notification settings - Fork 14.1k
[clang] Reject VLAs in __is_layout_compatible()
#87737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This is a follow-up to llvm#81506. Since `__is_layout_compatible()` is a C++ intrinsic (https://github.com/llvm/llvm-project/blob/ff1e72d68d1224271801ff5192a8c14fbd3be83b/clang/include/clang/Basic/TokenKinds.def#L523), I don't think we should define how it interacts with VLA extension unless we have a compelling reason to. Since llvm#81506 was merged after 18 cut-off, we don't have to follow any kind of deprecation process.
@llvm/pr-subscribers-clang Author: Vlad Serebrennikov (Endilll) ChangesThis is a follow-up to #81506. Since
Since #81506 was merged after 18 cut-off, we don't have to follow any kind of deprecation process. Full diff: https://github.com/llvm/llvm-project/pull/87737.diff 2 Files Affected:
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 76bb78aa8b5458..db84f181012268 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -6026,6 +6026,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
return false;
}
case BTT_IsLayoutCompatible: {
+ if (LhsT->isVariableArrayType() || RhsT->isVariableArrayType())
+ Self.Diag(KeyLoc, diag::err_vla_unsupported)
+ << 1 << tok::kw___is_layout_compatible;
return Self.IsLayoutCompatible(LhsT, RhsT);
}
default: llvm_unreachable("not a BTT");
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index 14ec17989ec7c7..28653e82e5a16e 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1741,8 +1741,10 @@ void is_layout_compatible(int n)
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[n], int[2]));
+ // expected-error@-1 {{variable length arrays are not supported for '__is_layout_compatible'}}
+ static_assert(!__is_layout_compatible(int[n], int[n]));
+ // expected-error@-1 {{variable length arrays are not supported for '__is_layout_compatible'}}
static_assert(__is_layout_compatible(int&, int&));
static_assert(!__is_layout_compatible(int&, char&));
static_assert(__is_layout_compatible(void(int), void(int)));
|
I think the current behavior is reasonable-ish. Rejecting specific types is a bit weird... I think VLA should model incomplete types (but we currently don't reject that either, which is a bug) IE, I would expect __is_layout_compatible to return false in the presence of VLAs, incomplete types, and FAM |
My reading of your comment is that in the first paragraph you're asking both VLAs and incomplete types to be rejected, then in the second paragraph you're asking to extend the intrinsic to accept them and yield false. Can you pick one?
I'll address that in a follow-up PR, even though rejecting |
We should not reject (ie, make the programm ill-form) any type. Just return |
GCC rejects incomplete types: https://godbolt.org/z/xWbes5Wsc I think the behavior from GCC is defensible, so I think we should reject incomplete types, but accept flexible arrays. VLAs I'm ambivalent about because of the template instantiation behavior. CC @ldionne @philnik777 @mordante for libc++ perspective. |
The library does require complete types, interesting https://eel.is/c++draft/meta |
I think clang should reject incomplete types when the standard says so. It doesn't seem particularly useful to accept some special cases but reject incomplete types in general. All the traits should probably be audited once. It looks like Clang has other problematic cases: https://godbolt.org/z/hajWfq7a6 I don't really care whether Clang should reject VLAs when using the builtin, since the trait will be used through some template and that's rejected that anyways. FWIW it'd be more consistent, since in my mind Flexible arrays are accepted because they are arrays of unknown bounds in the type system, which is part of the standard. The extension is only that they aren't rejected at the end of a struct and have some special meaning there. They should definitely not be rejected. |
In my reading, http://eel.is/c++draft/basic.types.general#11 makes any type layout-compatible with itself, and even ignores cv-qualification:
I find the gap between core language term and type trait rather unfortunate. |
There are a lot of gaps between core language terms and type traits. For another example, copy constructible in the library is quite different from it in the language, volatile types are almost entirely ignored by the library, etc. At the end of the day, these builtins are intended to be used as the underlying implementation for the type traits, so when in doubt, following the library rules is usually a safe bet. |
static_assert(!__is_layout_compatible(int[n], int[n])); // FIXME: VLAs should be rejected | ||
static_assert(!__is_layout_compatible(int[n], int[2])); | ||
// expected-error@-1 {{variable length arrays are not supported for '__is_layout_compatible'}} | ||
static_assert(!__is_layout_compatible(int[n], int[n])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recognize that discussion has spiraled out of VLAs into incomplete types and flexible array members, but can I keep the original scope of this PR, focusing on just VLAs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with splitting the work across multiple patches so long as we get to the desired end state (or have issues filed to track what that end state should be).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, other items will be addressed in subsequent PRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think focusing on VLAs here is fine, that was the original scope and I don't see an urgent need to expand it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following discussions, LGTM but I'd like to make sure incomplete types don't fall through the cracks
This is a follow-up to llvm#81506. As discussed in llvm#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 (llvm#87737 (comment)), I added a couple of tests for that as well.
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.
This is a follow-up to #81506. Since
__is_layout_compatible()
is a C++ intrinsic (llvm-project/clang/include/clang/Basic/TokenKinds.def
Line 523 in ff1e72d
Since #81506 was merged after 18 cut-off, we don't have to follow any kind of deprecation process.