egorzhdan created this revision.
egorzhdan added a reviewer: gchatelet.
Herald added a project: All.
egorzhdan requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This change teaches the Sema logic for `__builtin_memcpy_inline` to implicitly 
convert arrays passed as arguments to pointers, similarly to regular `memcpy`.

This code will no longer cause a compiler crash:

  void f(char *p) {
      char s[1] = {0};
      __builtin_memcpy_inline(p, s, 1);
  }

rdar://88147527


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121475

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/builtins-memcpy-inline.cpp


Index: clang/test/Sema/builtins-memcpy-inline.cpp
===================================================================
--- clang/test/Sema/builtins-memcpy-inline.cpp
+++ clang/test/Sema/builtins-memcpy-inline.cpp
@@ -36,3 +36,9 @@
   // we do not try to evaluate size in non intantiated templates.
   __builtin_memcpy_inline(dst, src, size);
 }
+
+void test_memcpy_inline_implicit_conversion(void *ptr) {
+  char a[5];
+  __builtin_memcpy_inline(ptr, a, 5);
+  __builtin_memcpy_inline(a, ptr, 5);
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1943,6 +1943,17 @@
   case Builtin::BI__builtin_nontemporal_store:
     return SemaBuiltinNontemporalOverloaded(TheCallResult);
   case Builtin::BI__builtin_memcpy_inline: {
+    auto ArgArrayConversion = [&](unsigned Arg) {
+      ExprResult ArgExpr =
+          DefaultFunctionArrayLvalueConversion(TheCall->getArg(Arg));
+      if (ArgExpr.isInvalid())
+        return true;
+      TheCall->setArg(Arg, ArgExpr.get());
+      return false;
+    };
+
+    if (ArgArrayConversion(0) || ArgArrayConversion(1))
+      return true;
     clang::Expr *SizeOp = TheCall->getArg(2);
     // We warn about copying to or from `nullptr` pointers when `size` is
     // greater than 0. When `size` is value dependent we cannot evaluate its


Index: clang/test/Sema/builtins-memcpy-inline.cpp
===================================================================
--- clang/test/Sema/builtins-memcpy-inline.cpp
+++ clang/test/Sema/builtins-memcpy-inline.cpp
@@ -36,3 +36,9 @@
   // we do not try to evaluate size in non intantiated templates.
   __builtin_memcpy_inline(dst, src, size);
 }
+
+void test_memcpy_inline_implicit_conversion(void *ptr) {
+  char a[5];
+  __builtin_memcpy_inline(ptr, a, 5);
+  __builtin_memcpy_inline(a, ptr, 5);
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -1943,6 +1943,17 @@
   case Builtin::BI__builtin_nontemporal_store:
     return SemaBuiltinNontemporalOverloaded(TheCallResult);
   case Builtin::BI__builtin_memcpy_inline: {
+    auto ArgArrayConversion = [&](unsigned Arg) {
+      ExprResult ArgExpr =
+          DefaultFunctionArrayLvalueConversion(TheCall->getArg(Arg));
+      if (ArgExpr.isInvalid())
+        return true;
+      TheCall->setArg(Arg, ArgExpr.get());
+      return false;
+    };
+
+    if (ArgArrayConversion(0) || ArgArrayConversion(1))
+      return true;
     clang::Expr *SizeOp = TheCall->getArg(2);
     // We warn about copying to or from `nullptr` pointers when `size` is
     // greater than 0. When `size` is value dependent we cannot evaluate its
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to