hokein added inline comments.
================ Comment at: clang/lib/AST/ExprConstant.cpp:4583 if (!InitE) return getDefaultInitValue(VD->getType(), Val); ---------------- rsmith wrote: > The initializer might also be null because the variable is type-dependent > (eg, `X<contains_errors> x;`), in which case assuming default-init is wrong. > We should check for that and treat it like a value-dependent initializer. I think you're right, added the check here, but unfortunately I didn't see noticeable behavior changes, and didn't manage to construct one (I confirmed that `decltype(invalid()) x;` will trigger this path). ================ Comment at: clang/lib/AST/ExprConstant.cpp:4961 } + if (IS->getCond()->isValueDependent()) + return EvaluateDependentExpr(IS->getCond(), Info); ---------------- rsmith wrote: > rsmith wrote: > > hokein wrote: > > > The `if` stmt (the same to `while`, `for`) is tricky -- if the condition > > > is value-dependent, then we don't know which branch we should run into. > > > > > > - returning a ESR_Succeeded may lead to a bogus diagnostic ("reach the > > > end of the function"); > > > - returning a ESR_Failed may lead to a bogus diagnostic ("never produce a > > > constexpr"); > > > > > > I guess what we want is to stop the evaluation, and indicate that we hit > > > a value-dependent expression and we don't know how to evaluate it, but > > > still treat the constexpr function as potential constexpr (but no extra > > > diagnostics being emitted), but the current `EvalStmtResult` is not > > > sufficient, maybe we need a new enum. > > We should only produce the "never produce a constant expression" diagnostic > > if we also produce a CCEDiag/FFDiag, so I think returning ESR_Failed here > > should work. > Should this check live in EvaluateCond instead? > Should this check live in EvaluateCond instead? there is a subtle difference -- doing it outside (not matter succeed or fail) will stop any execution of the following code, while doing it in `EvaluateCond` may continue the remaining code path if it succeeds, which may introduce bogus diagnostics, e.g. emitting a diagnostic `constexpr evaluation hit maximum step limit; possible infinite loop?` for the following example. ``` constexpr int foo() { while (invalid()) {} return 1; } ``` Another point is that -- looks like if we just return `false` if it is a value-dependent expr in `EvaluateCond`, it improves diagnostics (` function never produces ` and `reached end of` diagnostics are suppressed) for the following example ``` constexpr int test4() { // expected-error {{constexpr function never produces a constant expression}} if (invalid()) // expected-error {{use of undeclared identifier}} return 1; else return 0; } // expected-note {{control reached end of constexpr function}} ``` ================ Comment at: clang/lib/AST/ExprConstant.cpp:5053 FullExpressionRAII IncScope(Info); if (!EvaluateIgnoredValue(Info, FS->getInc()) || !IncScope.destroy()) return ESR_Failed; ---------------- rsmith wrote: > Missing value dependence check here. ah, right. Added one test. ================ Comment at: clang/lib/AST/ExprConstant.cpp:8440 } else { + if (SubExpr->isValueDependent()) + return EvaluateDependentExpr(SubExpr, Info); ---------------- rsmith wrote: > How does this happen? I think this is a similar escaped case to CXXNewExpr as well. ================ Comment at: clang/lib/AST/ExprConstant.cpp:9145 } else if (Init) { + if (Init->isValueDependent()) + return EvaluateDependentExpr(Init, Info); ---------------- rsmith wrote: > How does this happen? Do we not propagate value-dependence from initializers > to new-expressions? this happens in the following case (during the constructor call), the dependence-bits of `CXXNewExpr` are correct -- it is value-dependent, instantiation-dependent, contains-errors. However, we run into this codepath because the `CXXDefaultInitExpr` doesn't have any dependence-bits being set, in fact, it is always none, I think this is a bug, fixing in https://reviews.llvm.org/D87382. With that fix, we don't need this check anymore (the same to other two places). ``` struct A { int* p = new int(invalid()); } constexpr int test2() { A a; return 1; } ``` Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D84637/new/ https://reviews.llvm.org/D84637 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits