diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index ce69bad36a1a1..6b47b8a125647 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9545,6 +9545,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, // Figure out how many T's we're copying. uint64_t TSize = Info.Ctx.getTypeSizeInChars(T).getQuantity(); + if (TSize == 0) + return false; if (!WChar) { uint64_t Remainder; llvm::APInt OrigN = N; diff --git a/clang/test/Sema/builtin-memcpy.c b/clang/test/Sema/builtin-memcpy.c new file mode 100644 index 0000000000000..953ebddb9c8df --- /dev/null +++ b/clang/test/Sema/builtin-memcpy.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify=c +// RUN: %clang_cc1 -x c++ %s -fsyntax-only -verify=cxx + +// cxx-no-diagnostics + + +/// Zero-sized structs should not crash. +int b() { + struct { } a[10]; + __builtin_memcpy(&a[2], a, 2); // c-warning {{buffer has size 0, but size argument is 2}} + return 0; +} + +#ifdef __cplusplus +// FIXME: This is UB and GCC correctly diagnoses it. Clang should do the same. +constexpr int b2() { + struct { } a[10]; + __builtin_memcpy(&a[2], a, 2); + return 0; +} +static_assert(b2() == 0, ""); +#endif