llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Corentin Jabot (cor3ntin) <details> <summary>Changes</summary> In #<!-- -->143667, we made constant evaluation fail on `*null_ptr`, as this is UB. However, `&(*(foo*)0)` seems to be a common pattern, which made #<!-- -->143667 too disruptive. So instead of failing the evaluation, we note the UB, which let clang recovers when checking for constant initialization. Fixes #<!-- -->149500 --- Full diff: https://github.com/llvm/llvm-project/pull/149648.diff 4 Files Affected: - (modified) clang/lib/AST/ExprConstant.cpp (+6-3) - (modified) clang/test/AST/ByteCode/const-eval.c (-2) - (modified) clang/test/Sema/const-eval.c (+4-3) - (modified) clang/test/SemaCXX/constant-expression-cxx14.cpp (+5) ``````````diff diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index cfc4729be4184..e07dd317cfb3b 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9346,9 +9346,12 @@ bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { // [C++26][expr.unary.op] // If the operand points to an object or function, the result // denotes that object or function; otherwise, the behavior is undefined. - return Success && - (!E->getType().getNonReferenceType()->isObjectType() || - findCompleteObject(Info, E, AK_Dereference, Result, E->getType())); + // Because &(*(type*)0) is a common pattern, we do not fail the evaluation + // immediately. + if (!Success || !E->getType().getNonReferenceType()->isObjectType()) + return Success; + return !!findCompleteObject(Info, E, AK_Dereference, Result, E->getType()) || + Info.noteUndefinedBehavior(); } bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { diff --git a/clang/test/AST/ByteCode/const-eval.c b/clang/test/AST/ByteCode/const-eval.c index c8651a744f969..eab14c08ec809 100644 --- a/clang/test/AST/ByteCode/const-eval.c +++ b/clang/test/AST/ByteCode/const-eval.c @@ -51,8 +51,6 @@ struct s { }; EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1)); -// ref-error@-1 {{expression is not an integer constant expression}} \ -// ref-note@-1 {{dereferencing a null pointer}} #ifndef NEW_INTERP EVAL_EXPR(20, __builtin_constant_p(*((int*) 10))); diff --git a/clang/test/Sema/const-eval.c b/clang/test/Sema/const-eval.c index 87c21120e7c5d..11cc7fbc0feb3 100644 --- a/clang/test/Sema/const-eval.c +++ b/clang/test/Sema/const-eval.c @@ -41,9 +41,6 @@ struct s { }; EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1)); -// expected-error@-1 {{not an integer constant expression}} \ -// expected-note@-1 {{dereferencing a null pointer is not allowed in a constant expression}} - EVAL_EXPR(20, __builtin_constant_p(*((int*) 10))); @@ -153,3 +150,7 @@ struct PR35214_X { int PR35214_x; int PR35214_y = ((struct PR35214_X *)&PR35214_x)->arr[1]; // expected-error {{not a compile-time constant}} int *PR35214_z = &((struct PR35214_X *)&PR35214_x)->arr[1]; // ok, &PR35214_x + 2 + + +int * GH149500_p = &(*(int *)0x400); +static const void *GH149500_q = &(*(const struct sysrq_key_op *)0); diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp index 182c0d01141ff..1743e0e3ac4b5 100644 --- a/clang/test/SemaCXX/constant-expression-cxx14.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp @@ -1445,3 +1445,8 @@ static_assert(test_member_null(), ""); } } + +namespace GH149500 { + unsigned int * p = &(*(unsigned int *)0x400); + static const void *q = &(*(const struct sysrq_key_op *)0); +} `````````` </details> https://github.com/llvm/llvm-project/pull/149648 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits