Trying to compile the following example results in a clang crash:
$ cat char.c void *memcpy(void *, const void *, unsigned int); extern char array2[]; extern char array[]; void test(void) { memcpy(&array, &array2, 9 * sizeof(char)); } $ ./llvm/build/bin/clang -target armv8a-none-eabi -c char.c clang-8: /work/llvm/lib/Support/APInt.cpp:1785: static void llvm::APInt::udivrem(const llvm::APInt&, uint64_t, llvm::APInt&, uint64_t&): Assertion `RHS != 0 && "Divide by zero?"' failed. [...]
The problem occurs since rC338941. The change added support for constant evaluation of __builtin_memcpy/memmove() but it does not always cope well with incomplete types.
The AST for the memcpy() call looks as follows:
CallExpr 0x7416d0 'void *' |-ImplicitCastExpr 0x7416b8 'void *(*)(void *, const void *, unsigned int)' <FunctionToPointerDecay> | `-DeclRefExpr 0x741518 'void *(void *, const void *, unsigned int)' Function 0x741198 'memcpy' 'void *(void *, const void *, unsigned int)' |-ImplicitCastExpr 0x741710 'void *' <BitCast> | `-UnaryOperator 0x741598 'char (*)[]' prefix '&' cannot overflow | `-DeclRefExpr 0x741540 'char []' lvalue Var 0x741358 'array' 'char []' |-ImplicitCastExpr 0x741728 'const void *' <BitCast> | `-UnaryOperator 0x7415e0 'char (*)[]' prefix '&' cannot overflow | `-DeclRefExpr 0x7415b8 'char []' lvalue Var 0x741298 'array2' 'char []' `-BinaryOperator 0x741668 'unsigned int' '*' |-ImplicitCastExpr 0x741650 'unsigned int' <IntegralCast> | `-IntegerLiteral 0x741600 'int' 9 `-UnaryExprOrTypeTraitExpr 0x741630 'unsigned int' sizeof 'char'
The following happens in PointerExprEvaluator::VisitBuiltinCallExpr(), label Builtin::BI__builtin_memcpy:
- Types T and SrcT are determined as:
IncompleteArrayType 0x741250 'char []' `-BuiltinType 0x6ff430 'char'
- Method ASTContext::getTypeSizeInChars() is called to obtain size of type T. It returns 0 because the type is incomplete. The result is stored in variable TSize.
- Following call to llvm::APInt::udivrem(OrigN, TSize, N, Remainder) fails because it attempts a divide by zero.
The proposed patch fixes the problem by adding a check that no incomplete type is getting copied prior to the call to ASTContext::getTypeSizeInChars().
Nit: add an underscore between incomplete and type.