llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> Add a test for type punning and tests and the necessary checks for non-trivially-copyable types and incomplete types. --- Full diff: https://github.com/llvm/llvm-project/pull/135975.diff 2 Files Affected: - (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+17-1) - (modified) clang/test/AST/ByteCode/builtin-functions.cpp (+35) ``````````diff diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index b694a34e47ee0..31d97d9060142 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1872,7 +1872,23 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, return false; } - // Check if we have enough elements to read from and write to/ + if (DestElemType->isIncompleteType() || + DestPtr.getType()->isIncompleteType()) { + QualType DiagType = + DestElemType->isIncompleteType() ? DestElemType : DestPtr.getType(); + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_memcpy_incomplete_type) + << Move << DiagType; + return false; + } + + if (!DestElemType.isTriviallyCopyableType(ASTCtx)) { + S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_nontrivial) + << Move << DestElemType; + return false; + } + + // Check if we have enough elements to read from and write to. size_t RemainingDestBytes = RemainingDestElems * DestElemSize; size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize; if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) { diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index a57b4530d2264..a4c8ec4856ecc 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -33,6 +33,30 @@ extern "C" { extern wchar_t *wmemcpy(wchar_t *d, const wchar_t *s, size_t n); } + +constexpr int test_address_of_incomplete_array_type() { // both-error {{never produces a constant expression}} + extern int arr[]; + __builtin_memmove(&arr, &arr, 4 * sizeof(arr[0])); // both-note 2{{cannot constant evaluate 'memmove' between objects of incomplete type 'int[]'}} + return arr[0] * 1000 + arr[1] * 100 + arr[2] * 10 + arr[3]; +} +static_assert(test_address_of_incomplete_array_type() == 1234, ""); // both-error {{constant}} \ + // both-note {{in call}} + + + struct NonTrivial { + constexpr NonTrivial() : n(0) {} + constexpr NonTrivial(const NonTrivial &) : n(1) {} + int n; + }; + constexpr bool test_nontrivial_memcpy() { // ref-error {{never produces a constant}} + NonTrivial arr[3] = {}; + __builtin_memcpy(arr, arr + 1, sizeof(NonTrivial)); // both-note {{non-trivially-copyable}} \ + // ref-note {{non-trivially-copyable}} + return true; + } + static_assert(test_nontrivial_memcpy()); // both-error {{constant}} \ + // both-note {{in call}} + namespace strcmp { constexpr char kFoobar[6] = {'f','o','o','b','a','r'}; constexpr char kFoobazfoobar[12] = {'f','o','o','b','a','z','f','o','o','b','a','r'}; @@ -1349,6 +1373,17 @@ namespace BuiltinMemcpy { // both-note {{source of 'memcpy' is (void *)123}} static_assert(__builtin_memcpy(fold(reinterpret_cast<wchar_t*>(123)), &global, sizeof(wchar_t))); // both-error {{not an integral constant expression}} \ // both-note {{destination of 'memcpy' is (void *)123}} + + + constexpr float type_pun(const unsigned &n) { + float f = 0.0f; + __builtin_memcpy(&f, &n, 4); // both-note {{cannot constant evaluate 'memcpy' from object of type 'const unsigned int' to object of type 'float'}} + return f; + } + static_assert(type_pun(0x3f800000) == 1.0f); // both-error {{constant}} \ + // both-note {{in call}} + + } namespace Memcmp { `````````` </details> https://github.com/llvm/llvm-project/pull/135975 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits