Title
Out-of-lifetime lvalue-to-rvalue conversion
Status
c++14
Section
7.3.2 [conv.lval]
Submitter
Canada

Created on 2013-09-24.00:00:00 last changed 81 months ago

Messages

Date: 2014-02-15.00:00:00

[Moved to DR at the February, 2014 meeting.]

Date: 2013-09-15.00:00:00

Proposed resolution (September, 2013):

Change 7.3.2 [conv.lval] paragraph 2 as follows:

When an lvalue-to-rvalue conversion occurs in an unevaluated operand or a subexpression thereof (Clause Clause 7 [expr]) is applied to an expression e, and either

  • e is not potentially evaluated, or

  • the evaluation of e results in the evaluation of a member ex of the set of potential results of e, and ex names a variable x that is not odr-used by ex (6.3 [basic.def.odr]),

the value contained in the referenced object is not accessed. [Example:

  struct S { int n; };
  auto f() {
    S x { 1 };
    constexpr S y { 2 };
    return [&](bool b) { return (b ? y : x).n; };
  }
  auto g = f();
  int m = g(false); // undefined behavior due to access of x.n outside its lifetime
  int n = g(true);  // OK, does not access y.n

end example] In all other cases, the result of the conversion...

Date: 2013-09-24.00:00:00
N3690 comment CA 14

Consider an example like the following:

  struct Base { 
    virtual int call() = 0; 
  }; 
  Base *foo() { 
    constexpr int x = 0; 
    struct Local : Base { 
      virtual int call() { return x; } 
    }; 
    static Local local; 
    return &local; 
  } 

  int main() { 
    return foo()->call(); 
  } 

While the likely intention is that the lvalue-to-rvalue conversion of the block-scope constant is implemented by using the value of the constant expression in place of reading from storage, it seems that the wording of 7.3.2 [conv.lval] paragraph 2 does not prevent this program from being subject to undefined behaviour caused by lifetime violation. In particular, it seems that a name expression that appears in a potentially-evaluated expression such that the object named is not odr-used (by that instance of the name) may still be evaluated, in theory, as an lvalue through which the object named or a subobject thereof is accessed.

History
Date User Action Args
2014-11-24 00:00:00adminsetstatus: dr -> c++14
2014-03-03 00:00:00adminsetmessages: + msg4933
2014-03-03 00:00:00adminsetstatus: ready -> dr
2013-10-14 00:00:00adminsetmessages: + msg4571
2013-09-24 00:00:00admincreate