diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -560,7 +560,7 @@ BUILTIN(__builtin_stdarg_start, "vA.", "nt") BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nctE") BUILTIN(__builtin_bcmp, "ivC*vC*z", "FnE") -BUILTIN(__builtin_bcopy, "vv*v*z", "n") +BUILTIN(__builtin_bcopy, "vvC*v*z", "nF") BUILTIN(__builtin_bzero, "vv*z", "nF") BUILTIN(__builtin_free, "vv*", "nF") BUILTIN(__builtin_malloc, "v*z", "nF") @@ -1156,6 +1156,7 @@ LIBBUILTIN(index, "c*cC*i", "f", STRINGS_H, ALL_GNU_LANGUAGES) LIBBUILTIN(rindex, "c*cC*i", "f", STRINGS_H, ALL_GNU_LANGUAGES) LIBBUILTIN(bzero, "vv*z", "f", STRINGS_H, ALL_GNU_LANGUAGES) +LIBBUILTIN(bcopy, "vvC*v*z", "f", STRINGS_H, ALL_GNU_LANGUAGES) LIBBUILTIN(bcmp, "ivC*vC*z", "fE", STRINGS_H, ALL_GNU_LANGUAGES) // In some systems str[n]casejmp is a macro that expands to _str[n]icmp. // We undefine then here to avoid wrong name. diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4356,6 +4356,10 @@ case Builtin::BIbzero: return Builtin::BIbzero; + case Builtin::BI__builtin_bcopy: + case Builtin::BIbcopy: + return Builtin::BIbcopy; + case Builtin::BIfree: return Builtin::BIfree; @@ -4387,6 +4391,8 @@ return Builtin::BIstrlen; if (FnInfo->isStr("bzero")) return Builtin::BIbzero; + if (FnInfo->isStr("bcopy")) + return Builtin::BIbcopy; } else if (isInStdNamespace()) { if (FnInfo->isStr("free")) return Builtin::BIfree; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3618,6 +3618,20 @@ Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false); return RValue::get(nullptr); } + + case Builtin::BIbcopy: + case Builtin::BI__builtin_bcopy: { + Address Src = EmitPointerWithAlignment(E->getArg(0)); + Address Dest = EmitPointerWithAlignment(E->getArg(1)); + Value *SizeVal = EmitScalarExpr(E->getArg(2)); + EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(1)->getType(), + E->getArg(1)->getExprLoc(), FD, 1); + Builder.CreateMemMove(Dest, Src, SizeVal, false); + return RValue::get(Dest.getPointer()); + } + case Builtin::BImemcpy: case Builtin::BI__builtin_memcpy: case Builtin::BImempcpy: diff --git a/clang/test/Analysis/bstring.c b/clang/test/Analysis/bstring.c --- a/clang/test/Analysis/bstring.c +++ b/clang/test/Analysis/bstring.c @@ -483,8 +483,7 @@ //===----------------------------------------------------------------------=== #define bcopy BUILTIN(bcopy) -// __builtin_bcopy is not defined with const in Builtins.def. -void bcopy(/*const*/ void *s1, void *s2, size_t n); +void bcopy(const void *s1, void *s2, size_t n); void bcopy0 (void) { diff --git a/clang/test/Analysis/security-syntax-checks.m b/clang/test/Analysis/security-syntax-checks.m --- a/clang/test/Analysis/security-syntax-checks.m +++ b/clang/test/Analysis/security-syntax-checks.m @@ -77,9 +77,9 @@ } // Obsolete function bcopy -void bcopy(void *, void *, size_t); +void bcopy(const void *, void *, size_t); -void test_bcopy(void *a, void *b, size_t n) { +void test_bcopy(const void *a, void *b, size_t n) { bcopy(a, b, n); // expected-warning{{The bcopy() function is obsoleted by memcpy() or memmove(}} } diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c --- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-macros.c @@ -167,15 +167,15 @@ } // 64BIT-LABEL: @testbcopy( -// 64BIT: call void @bcopy(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i64 noundef {{%.*}}) +// 64BIT: call void @llvm.memmove.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 {{%.*}}, i1 false) // 64BIT-NEXT: ret void // // 32BIT-LABEL: @testbcopy( -// 32BIT: call void @bcopy(ptr noundef {{%.*}}, ptr noundef {{%.*}}, i32 noundef {{%.*}}) +// 32BIT: call void @llvm.memmove.p0.p0.i32(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i32 {{%.*}}, i1 false) // 32BIT-NEXT: ret void // void testbcopy(const void *src, void *dest, size_t n) { - __bcopy(src, dest, n); + bcopy(src, dest, n); } // 64BIT-LABEL: @testbzero(