serge-sans-paille created this revision. serge-sans-paille added a reviewer: aaron.ballman. Herald added a project: All. serge-sans-paille requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
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. Fix issue #39324. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D124038 Files: clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constant-expression-cxx11.cpp Index: clang/test/SemaCXX/constant-expression-cxx11.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx11.cpp +++ clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1595,10 +1595,13 @@ namespace CompoundLiteral { // Matching GCC, file-scope array compound literals initialized by constants // are lifetime-extended. - constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}} + constexpr int *p = (int*)(const int[1]){3}; // expected-warning {{C99}} static_assert(*p == 3, ""); static_assert((int[2]){1, 2}[1] == 2, ""); // expected-warning {{C99}} + constexpr int *q = (int *)(int[1]){3}; // expected-warning {{C99}} + static_assert(*q == 3, ""); // expected-error {{constant expression}} + // Other kinds are not. struct X { int a[2]; }; constexpr int *n = (X){1, 2}.a; // expected-warning {{C99}} expected-warning {{temporary}} Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -4289,6 +4289,17 @@ } } + if (const VarDecl *VD = dyn_cast_or_null<const VarDecl>( + LVal.Base.dyn_cast<const ValueDecl *>())) { + if (const CompoundLiteralExpr *CLE = dyn_cast_or_null<CompoundLiteralExpr>( + VD->getAnyInitializer()->IgnoreCasts())) { + QualType CLET = CLE->getType().getCanonicalType(); + if (!CLET.isConstant(Info.Ctx)) { + Info.FFDiag(Conv); + } + } + } + CompleteObject Obj = findCompleteObject(Info, Conv, AK, LVal, Type); return Obj && extractSubobject(Info, Conv, Obj, LVal.Designator, RVal, AK); }
Index: clang/test/SemaCXX/constant-expression-cxx11.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx11.cpp +++ clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1595,10 +1595,13 @@ namespace CompoundLiteral { // Matching GCC, file-scope array compound literals initialized by constants // are lifetime-extended. - constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}} + constexpr int *p = (int*)(const int[1]){3}; // expected-warning {{C99}} static_assert(*p == 3, ""); static_assert((int[2]){1, 2}[1] == 2, ""); // expected-warning {{C99}} + constexpr int *q = (int *)(int[1]){3}; // expected-warning {{C99}} + static_assert(*q == 3, ""); // expected-error {{constant expression}} + // Other kinds are not. struct X { int a[2]; }; constexpr int *n = (X){1, 2}.a; // expected-warning {{C99}} expected-warning {{temporary}} Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -4289,6 +4289,17 @@ } } + if (const VarDecl *VD = dyn_cast_or_null<const VarDecl>( + LVal.Base.dyn_cast<const ValueDecl *>())) { + if (const CompoundLiteralExpr *CLE = dyn_cast_or_null<CompoundLiteralExpr>( + VD->getAnyInitializer()->IgnoreCasts())) { + QualType CLET = CLE->getType().getCanonicalType(); + if (!CLET.isConstant(Info.Ctx)) { + Info.FFDiag(Conv); + } + } + } + CompleteObject Obj = findCompleteObject(Info, Conv, AK, LVal, Type); return Obj && extractSubobject(Info, Conv, Obj, LVal.Designator, RVal, AK); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits