Document:  WG21 N3914
Author:    William M. (Mike) Miller
Edison Design Group, Inc.
Date:   2014-02-14





Additional Core Language Issue Resolutions for Issaquah

The following issue resolutions, in addition to those in "ready" and "tentatively ready" status in document N3833, have been approved by the Core Language Working Group to be applied to the DIS.




1466. Visible sequences of side effects are redundant

Proposed resolution:

  1. Change 1.10 [intro.multithread] paragraph 14 as follows:

  2. The visible sequence of side effects on an atomic object M, with respect to a value computation B of M, is a maximal contiguous sub-sequence of side effects in the modification order of M, where the first side effect is visible with respect to B, and for every side effect, it is not the case that B happens before it. The value of an atomic object M, as determined by evaluation B, shall be the value stored by some operation in the visible sequence of M with respect to B side effect A that modifies M, where B does not happen before A. [Note: It can be shown that the visible sequence of side effects of a value computation is unique given The set of such side effects is also restricted by the rest of the rules described here, and in particular, by the coherence requirements below. —end note]
  3. Change 1.10 [intro.multithread] paragraph 20 as follows:

  4. [Note: The visible sequence of side effects value observed by a load of an atomic depends on the “happens before” relation, which depends on the values observed by loads of atomics, which we are restricting here. The intended reading is that there must exist an association of atomic loads with modifications they observe that, together with suitably chosen modification orders and the “happens before” relation derived as described above, satisfy the resulting constraints as imposed here. —end note]
  5. Change 1.10 [intro.multithread] paragraph 22 as follows:

  6. [Note: Compiler transformations that introduce assignments to a potentially shared memory location that would not be modified by the abstract machine are generally precluded by this standard, since such an assignment might overwrite another assignment by a different thread in cases in which an abstract machine execution would not have encountered a data race. This includes implementations of data member assignment that overwrite adjacent members in separate memory locations. Reordering of atomic loads in cases in which the atomics in question may alias is also generally precluded, since this may violate the “visible sequence” coherence rules. —end note]
  7. Change 29.3 [atomics.order] paragraph 3 as follows:

  8. There shall be a single total order S on all memory_order_seq_cst operations, consistent with the “happens before” order and modification orders for all affected locations, such that each memory_order_seq_cst operation B that loads a value from an atomic object M observes one of the following values:

    [Note:...




1673. Clarifying overload resolution for the second step of copy-initialization

Proposed resolution:

Change 13.3.3.1 [over.best.ics] paragraph 4 as follows:

However, when considering the argument of a constructor or user-defined conversion function that is a candidate by 13.3.1.3 [over.match.ctor] when invoked for the copying/moving of the temporary in the second step of a class copy-initialization, by 13.3.1.7 [over.match.list] when passing the initializer list as a single argument or when the initializer list has exactly one element and a conversion to some class X or reference to (possibly cv-qualified) X is considered for the first parameter of a constructor of X, or by 13.3.1.4 [over.match.copy], 13.3.1.5 [over.match.conv], or 13.3.1.6 [over.match.ref] in all cases, only standard conversion sequences and ellipsis conversion sequences are considered. if the target is

and the constructor or user-defined conversion function is a candidate by

user-defined conversion sequences are not considered. [Note: These rules prevent more than one user-defined conversion from being applied during overload resolution, thereby avoiding infinite recursion. —end note] [Example:

  struct Y { Y(int); };
  struct A { operator int(); };
  Y y1 = A();  // error: A::operator int() is not a candidate

  struct X { };
  struct B { operator X(); };
  B b;
  X x({b});    // error: B::operator X() is not a candidate

end example]




1759. UTF-8 code units in plain char

Proposed resolution:

  1. Change 2.14.5 [lex.string] paragraph 7 as follows:

  2. A string literal that begins with u8, such as u8"asdf", is a UTF-8 string literal and is initialized with the given characters as encoded in UTF-8.
  3. Insert the following as a new paragraph following 2.14.5 [lex.string] paragraph 8:
  4. For a UTF-8 string literal, each successive element of the object representation (3.9 [basic.types[) has the value of the corresponding code unit of the UTF-8 encoding of the string.
  5. Change 3.9.1 [basic.fundamental] paragraph 1 as follows:

  6. ...In any particular implementation, a plain char object can take on either the same values as a signed char or an unsigned char; which one is implementation-defined. For each value i of type unsigned char in the range 0 to 255 inclusive, there exists a value j of type char such that the result of an integral conversion (4.7 [conv.integral]) from i to char is j, and the result of an integral conversion from j to unsigned char is i.



1786. Effect of merging allocations on memory leakage

Proposed resolution:

  1. 1. Change 5.3.4 [expr.new] paragraph 10 as follows:

  2. An implementation is allowed to omit a call to a replaceable global allocation function (18.6.1.1 [new.delete.single], 18.6.1.2 [new.delete.array]). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another new-expression. The implementation may extend the allocation of a new-expression e1 to provide storage for a new-expression e2 if the lifetime of the object allocated by e1 strictly contains the lifetime of the object allocated by e2, e1 and e2 would invoke the same replaceable global allocation function, and, for a throwing allocation function, exceptions in e1 and e2 would be first caught in the same handler. following would be true were the allocation not extended:

    [Example:

      void mergeable(int x) {
        // These heap allocations are safe for merging:
        std::unique_ptr<char[]> a{new (std::nothrow) char[8]};
        std::unique_ptr<char[]> b{new (std::nothrow) char[8]};
        std::unique_ptr<char[]> c{new (std::nothrow) char[x]};
    
        g(a.get(), b.get(), c.get());
      }
    
      void unmergeable(int x) {
        std::unique_ptr<char[]> a{new char[8]};
        try {
          // Merging this allocation would change its catch handler.
           std::unique_ptr<char[]> b{new char[x]};
        } catch (const std::bad_alloc& e) {
          std::cerr << "Allocation failed: " << e.what() << std::endl;
          throw;
        }
      }
    

    end example]

  3. Change 5.3.5 [expr.delete] paragraph 7 as follows:

  4. If the value of the operand of the delete-expression is not a null pointer value, then:

    Otherwise, it is unspecified whether the deallocation function will be called. [Note:...




1787. Uninitialized unsigned char values

Proposed resolution:

  1. Change 3.3.2 [basic.scope.pdecl] paragraph 1 as follows:

  2. The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below. [Example:

      int unsigned char x = 12;
      { int unsigned char x = x; }
    

    Here the second x is initialized with its own (indeterminate) value. —end example]

  3. Change 4.1 [conv.lval] paragraph 2 as follows:

  4. When an lvalue-to-rvalue conversion occurs in an unevaluated operand or a subexpression thereof (Clause 5 [expr]) the value contained in the referenced object is not accessed. In all other cases, the result of the conversion is determined according to the following rules:

  5. Change 5.3.4 [expr.new] paragraph 17 as follows:

  6. A new-expression that creates an object of type T initializes that object as follows:

  7. Change 8.5 [dcl.init] paragraph 12 as follows:

  8. If no initializer is specified for an object, the object is default-initialized; if no initialization is performed,. When storage for an object with automatic or dynamic storage duration is obtained, the object has indeterminate value an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced (5.17 [expr.ass]). [Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2 [basic.start.init]. —end note] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

    [Example:

      int f(bool b) {
        unsigned char c;
        unsigned char d = c; // OK, d has an indeterminate value
        int e = d;           // undefined behavior
        return b ? d : 0;    // undefined behavior if b is true
      }
    

    end example]

  9. Change 12.6.2 [class.base.init] paragraph 8 as follows:

  10. ...An attempt to initialize more than one non-static data member of a union renders the program ill-formed. [Note: After the call to a constructor for class X for an object with automatic or dynamic storage duration has completed, if the constructor was not invoked as part of value-initialization and a member of X is neither initialized nor given a value during execution of the compound-statement of the body of the constructor, the member has an indeterminate value. end note] [Example:...