This is an archive of the discontinued LLVM Phabricator instance.

[Sema][SVE] Reject subscripts on pointers to sizeless types
ClosedPublic

Authored by rsandifo-arm on Mar 12 2020, 11:38 AM.

Details

Summary

clang currently accepts:

__SVInt8_t &foo1(__SVInt8_t *x) { return *x; }
__SVInt8_t &foo2(__SVInt8_t *x) { return x[1]; }

The first function is valid ACLE code and generates correct LLVM IR
(and assembly code). But the second function is invalid for the
same reason that arrays of sizeless types are. Trying to code-generate
the function leads to:

llvm/include/llvm/Support/TypeSize.h:126: uint64_t llvm::TypeSize::getFixedSize() const: Assertion `!IsScalable && "Request for a fixed size on a s

calable object"' failed.

This patch reports an appropriate diagnostic instead.

Diff Detail

Event Timeline

rsandifo-arm created this revision.Mar 12 2020, 11:38 AM

I'm not sure we actually want to reject this; let's discuss on the review for D76086, since subscripting is sort of a special case of arithmetic.

I'm not sure we actually want to reject this; let's discuss on the review for D76086, since subscripting is sort of a special case of arithmetic.

A silly corner case for this is:

template<typename T>
constexpr __SIZE_TYPE__ f(T *x) { return &x[1] - x; }
typedef int arr1[f((int *)0) - 1];
typedef int arr2[f((__SVInt8_t *)0) - 1];

which gives:

a.cpp:2:48: warning: subtraction of pointers to type '__SVInt8_t' of zero size has undefined behavior [-Wpointer-arith]
constexpr __SIZE_TYPE__ f(T *x) { return &x[1] - x; }
                                         ~~~~~ ^ ~
a.cpp:4:18: note: in instantiation of function template specialization 'f<__SVInt8_t>' requested here
typedef int arr2[f((__SVInt8_t *)0) - 1];
                 ^
a.cpp:4:13: error: variable length array declaration not allowed at file scope
typedef int arr2[f((__SVInt8_t *)0) - 1];
            ^

No real code would do anything like this of course. But I think it shows that it's going to be difficult to divide cases that measure sizeof only during CodeGen from those that measure it during Sema. With more and more things being accepted as constexprs, I think it's safer to treat any measure of sizeof as being at least potentially computable at compile time.

There's also the argument that this is what the spec says. I realise that's a fairly weak argument though, since the spec could always be changed.

We already support sizeof expressions where the result can't be computed at compile-time. For example: int f(int n, int (*p)[n]) { return sizeof(*p); }. (For constant contexts specifically, see HandleSizeof() in ExprConstant.cpp.) I think any argument that it would be hard to extend that to cover sizeless types is pretty weak.

Of course, just because we can support it doesn't mean we should. As a matter of language design, we might want to discourage users from writing that sort of thing. It could be argued either way.

efriedma accepted this revision.Mar 16 2020, 11:28 AM

This patch LGTM, at least for now.

This revision is now accepted and ready to land.Mar 16 2020, 11:28 AM
This revision was automatically updated to reflect the committed changes.