Bug 118461 - constexpr lifetime tracking allows access to out-of-lifetime const variables - re-entering the scope
Summary: constexpr lifetime tracking allows access to out-of-lifetime const variables ...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
: 118462 (view as bug list)
Depends on: 96630
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2025-01-13 22:29 UTC by Richard Smith
Modified: 2025-01-15 07:09 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2025-01-13 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Smith 2025-01-13 22:29:29 UTC
Even after the fix for PR96630, GCC still accepts this invalid code that accesses a variable outside its lifetime:

constexpr int f() {
  const int *p = 0;
  for (int i = 0; i != 2; ++i) {
    if (i == 1) { return *p; }
    const int n = 0;
    p = &n;
  }
}
static_assert(f() == 0);

(Live: https://godbolt.org/z/3fEEoq3T6)

Even though `*p` denotes `n`, which is usable in constant expressions, the evaluation of `*p` still has undefined behavior because `n` is not within its lifetime, so this is non-constant by [expr.const]/10.8.

Note in particular that the special provision in [expr.const]/17 that effectively says we get to ignore the lifetime rules in some cases does not apply to variables whose lifetime started within the evaluation. So this is valid:

void g() {
  const int n = 0;
  static_assert([] { return n; }() == 0);
}

... because we get to assume that n is alive throughout the evaluation, but the same doesn't apply in the testcase above, because the lifetime of the variable started within the evaluation of `f() == 0`.
Comment 1 Richard Smith 2025-01-13 22:35:07 UTC
See also PR118462 -- I'm not sure if these are duplicates or not; this one requires the variable to be declared `const`. However, GCC does reject this simplified testcase with a lifetime error:

constexpr int f() {
  const int *p = 0;
  {
    const int n = 0;
    p = &n;
  }
  return *p;
}
static_assert(f() == 0);

... suggesting that reentering the scope where `n` was declared is relevant.
Comment 2 Drea Pinski 2025-01-13 22:37:41 UTC
We don't yet handle other ways of
    accessing values outside their lifetime (e.g. following explicit
    destructor calls).
Comment 3 Drea Pinski 2025-01-13 22:41:44 UTC
*** Bug 118462 has been marked as a duplicate of this bug. ***
Comment 4 Drea Pinski 2025-01-13 22:44:23 UTC
.