[PATCH] D32372: Arrays of unknown bound in constant expressions
Richard Smith via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 21 14:30:55 PDT 2017
rsmith added a comment.
This needs testcases (the one from your summary plus the ones in my comments above would be good).
================
Comment at: lib/AST/ExprConstant.cpp:2622
// Next subobject is an array element.
- const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType);
- assert(CAT && "vla in literal type?");
+ uint64_t actualIndex;
+ const ArrayType *AT = Info.Ctx.getAsArrayType(ObjType); // non-null by assumption
----------------
I think this should be named `ArrayBound` or similar.
================
Comment at: lib/AST/ExprConstant.cpp:2625-2626
+ if (I == 0) {
+ /* we're dealing with the complete array object, which may have been declared
+ without a bound */
+ actualIndex = Sub.MostDerivedArraySize;
----------------
Use line comments, start with capital letter, end with period, please.
================
Comment at: lib/AST/ExprConstant.cpp:2627
+ without a bound */
+ actualIndex = Sub.MostDerivedArraySize;
+ assert(Sub.MostDerivedIsArrayElement && "Complete object is an array, but isn't?");
----------------
This will not be the correct bound in general. This field is the array size of the *innermost* non-base-class subobject described by the designator, not the outermost one.
You could compute the correct bound here by going back to the `ValueDecl*` in the `CompleteObject` and checking its most recent declaration, but I think it would be preferable to do that when computing the type in `findCompleteObject` instead.
(It might seem possible to map to the most recent `VarDecl` when evaluating the `DeclRefExpr` instead, but that actually won't work in general, for cases like:
```
extern int arr[];
constexpr int *p = arr; // computes APValue referring to first declaration of 'arr'
int arr[3];
constexpr int *q = p + 1; // should be accepted
```
... but `findCompleteObject` will happen late enough.)
================
Comment at: lib/AST/ExprConstant.cpp:5652-5653
return false;
- } else {
+ }
+ else {
Result.set(SubExpr, Info.CurrentCall->Index);
----------------
Per LLVM coding style, `else` goes on the same line as `}`.
================
Comment at: lib/AST/ExprConstant.cpp:5666
+ else if (auto decl = Result.Base.dyn_cast<ValueDecl const*>()) {
+ // make sure to consider the completed type.
+ if (auto CAT = Info.Ctx.getAsConstantArrayType(cast<ValueDecl const>(
----------------
Comments should start with a capital letter.
================
Comment at: lib/AST/ExprConstant.cpp:5670-5673
+ else {
+ Result.Designator.setInvalid();
+ CCEDiag(SubExpr, diag::note_constexpr_array_unknown_bound_decay);
+ }
----------------
Please suppress this diagnostic when `Info.checkingPotentialConstantExpression()`, since the expression is still potentially a constant expression. Example:
```
extern int arr[];
constexpr int *f() { return arr + 3; }
int arr[5];
constexpr int *p = f();
```
Here, when we check that the body of `f()` is valid, we need to ignore the fact that we don't know the array bound, since it could become known later.
================
Comment at: lib/AST/ExprConstant.cpp:5676
else
Result.Designator.setInvalid();
return true;
----------------
We should produce a `CCEDiag` along this path too. (This happens for VLAs.)
https://reviews.llvm.org/D32372
More information about the cfe-commits
mailing list