clang current accepts:
void foo1(__SVInt8_t *x, __SVInt8_t *y) { *x = *y; } void foo2(__SVInt8_t *x, __SVInt8_t *y) { memcpy(y, x, sizeof(__SVInt8_t)); }
The first function is valid ACLE code and generates correct LLVM IR.
The second function is invalid ACLE code and generates a zero-length
memcpy.
The point of this patch is to reject the use of sizeof in the second
case, rather than silently generating incorrect code.
There's no similar wrong-code bug for alignof. However, the SVE ACLE
conservatively treats alignof in the same way as sizeof, just as the
C++ standard does for incomplete types. The idea is that layout of
sizeless types is an implementation property and isn't defined at
the language level.
(We could relax the alignof rules in future if they turn out to be
too restrictive. It would be harder to go the other way though,
and forbid alignof after previously treating it as valid.)
Implementation-wise, the patch adds a new CompleteTypeKind enum
that controls whether RequireCompleteType & friends accept sizeless
built-in types. For now the default is to maintain the status quo
and accept sizeless types. However, the end of the series will flip
the default and remove the Default enum value.
The patch also adds new ...CompleteSized... wrappers that callers can
use if they explicitly want to reject sizeless types. The callers then
use diagnostics that have an extra 0/1 parameter to indicats whether
the type is sizeless or not.
The idea is to have three cases:
- calls that explicitly reject sizeless types, with a tweaked diagnostic for the sizeless case
- calls that explicitly allow sizeless types
- normal/old-style calls that don't make an explicit choice either way
Once the default is flipped, the 3. calls will conservatively reject
sizeless types, using the same diagnostic as for other incomplete types.