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

Reply via email to