When a non-const compound statement is used to initialize a constexpr pointer,
the pointed value is not const itself and cannot be folded at codegen time.
This matches GCC behavior for compund literal array
Fix issue #39324.
Differential D124038
[clang] Prevent folding of non-const compound expr serge-sans-paille on Apr 19 2022, 1:25 PM. Authored by
Details When a non-const compound statement is used to initialize a constexpr pointer, This matches GCC behavior for compund literal array Fix issue #39324.
Diff Detail
Event TimelineComment Actions The fix doesn't look right. A CompoundLiteralExpr is itself an lvalue; we should catch any issues when we visit it, not a VarDecl that contains a pointer to it. Comment Actions Well, the visitor for CompoundLiteralExpr explicitly states
Which is what I was trying to do in this patch. Comment Actions Alternatively, the following also works, but it splits the logic into anotherplace, while current patch is at least consistent with existing state diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 498f0d4..233307f 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3352,6 +3352,17 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, NoteLValueLocation(Info, Base); } + // In the particular case of CompoundLiteralExpr initialization, check that it is itself + // constant. + if (Info.InConstantContext) + if (const CompoundLiteralExpr *CLE = dyn_cast_or_null<CompoundLiteralExpr>( + VD->getAnyInitializer()->IgnoreCasts())) { + QualType CLET = CLE->getType().getCanonicalType(); + if (!CLET.isConstant(Info.Ctx)) { + Info.FFDiag(E); + } + } + Comment Actions The VD->getAnyInitializer()->IgnoreCasts() is the part that's wrong. We want to allow something like the following: constexpr int *q = (int *)(int[1]){3}; constexpr int *q2 = q; To catch the bad cases specifically, we have to wait until we actually reach the compound literal. See line 4262, or something like that. Comment Actions Match GCC behavior here: some test case were previously accepted while having the opposite behavior. This pacth both fixes the original issue and adopt gcc behavior.
Comment Actions Added reg to GCC info page to explain current behavior, and make the test more explicit with respect to that quote.
Comment Actions I think you're looking at old documentation? Here's what the current page (https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html) has to say:
Comment Actions Indeed! I was looking at my local Info Page. thanks for the extra pointer.
I can quote that part instead. I don't think this invalidates the actual code, right? At least with that commit the observable behavior gets closer to GCC, and it fixes https://github.com/llvm/llvm-project/issues/39324 |
Is the "isArrayType()" check here necessary?