Doc No: X3J16/97-0010 WG21/N1048 Date: January 28th, 1997 Project: Programming Language C++ Ref Doc: Reply to: Josee Lajoie (josee@vnet.ibm.com) +========================+ | Core WG List of Issues | +========================+ The first half of this document contains the substantive and editorial core issues. Because the core list of issues was not published in the post-Hawaii mailing, the issues that were closed at the Hawaii meeting are listed at the end of this document. +--------+ | Syntax | +--------+ 9.2 [class.mem]: 692: ";opt" after member "function-definition" should be omitted +-----------------+ | C Compatibility | +-----------------+ 1.1 [intro.scope]: 604: Should the C++ standard talk about features in C++ prior to 1985? Annex C: 680: Annex C subclause C.1 is out of date 743: Some anachronisms are missing from annex C Annex E: 770: The title of Annex E needs to be made shorter +---------------------+ | Lexical Conventions | +---------------------+ 2.3 [lex.trigraph]: 744: Is the description of trigraph processing wrong? +-------+ | Core1 | +-------+ Conformance model ----------------- 1.7 [intro.compliance]: 602: Are ill-formed programs with non-required diagnostics really necessary? 619: Is the definition of "resource limits" needed? Name Look Up ------------ 3.3.6 [basic.scope.class]: 664: When does the reevaluation rule for class scope name lookup require a diagnostic? 3.4.2 [basic.lookup.koenig]: 686: Where is a function name looked up if an argument type is introduced with a typedef or a using-declaration? 3.4.3 [basic.lookup.qual]: 665: In X::~Y is Y looked up in the context of the current expression? 3.4.5 [basic.lookup.classref]: 688: Rules for name lookup after :: . -> need to be clarified for conversion-function-id, template argument names and destructor names Linkage / ODR ------------- 3.2 [basic.def.odr]: 745: Does &inline_function yield the same result in all the translation units? 7.5 [dcl.link]: 729: Must extern "C" functions declared in a namespace and a global extern "C" function have different signatures and return types? 749: Can a declaration specify both a storage class and a linkage specification? 750: To which declarator in a member function declaration does the extern "C" specifier apply? 9.5 [class.union]: 505: Must anonymous unions declared in unnamed namespaces also be static? Object/Memory Model ------------------- 3.6.2 [basic.start.init]: 746: What is the order of initialization of a class static data member? 747: The term "static initialization" needs to be defined 5.3.4 [expr.new]: 669: semantics for new and delete expressions should be separated from the requirements for operator new and delete 690: Clarify the lookup of operator new in a new expression 5.7 [expr.add]: 720: Can you do &*p if p does not point to a valid object? 5.9 [expr.rel]: 721: Comparisons of pointer to class members need fine tuning 5.19 [expr.const]: 722: The definition of address constant expression needs fine tuning 7.3.3 [namespace.udecl]: 672: using-declarations and base class assignment operators 8.5 [dcl.init]: 751: Should { } be allowed around an initializer that is a string? 10.1 [class.mi]: 624: class with direct and indirect class of the same type: how can the base class members be referred to? 12.4 [class.dtor]: 753: Is 'new char[size]' aligned properly to hold an object of any type T? 12.5 [class.free]: 754: for new T, allocation functions in base classes of T are not considered 12.8 [class.copy]: 687: The WP prohobits the copy assignment of virtual base classes to behave like the copy constructor 755: Assignment of POD class objects: is the class copied as a block? +-------+ | Core2 | +-------+ Sequence Points/Execution Model ------------------------------- 1.8 [intro.execution]: 603: Do the WP constraints prevent multi-threading implementations? 694: List of full-expressions needed Access ------ 11.5 [class.protected]: 752: When accessing a base class member, the qualification is not ignored Types / Classes / Unions ------------------------ 3.9 [basic.life]: 621: The terms "same type" need to be defined Default Arguments ----------------- 8.3.6 [dcl.fct.default]: 689: What if two using-declarations refer to the same function but the declarations introduce different default-arguments? 730: When are default arguments for member functions of template classes semantically checked? Types Conversions / Function Overload Resolution ------------------------------------------------ 4.1 [conv.lval]: 711: Is an lvalue-to-rvalue conversion on an incomplete type allowed within a sizeof operand? 4.8 [conv.double]: 712: Is an lvalue-to-rvalue conversion on an incomplete type allowed within a sizeof operand? 5.2.2 [expr.call]: 713: What argument type can be passed to va_arg? 714: Is the term "default argument promotions" needed? 5.4 [expr.cast]: 718: Conversion to and from pointers to incomplete class types using old style casts - is this really implementation-defined? 7.2 [dcl.enum] 683: What is the underlying type of an enumeration type if the value of an enumerator uses the value of a previous enumerator? 13.3.3.1 [over.best.ics]: 733: Implicit conversion sequences and scalar types 13.6 [over.built]: 682: operator ?: and operands of enumeration types 734: ambiguity in "bool & ? void *& : classType&" where classType has an operator void*& 756: most uses of built-in "?" with class operands are ambiguous Expressions ----------- 5 [expr]: 748: Should we say that operator precedence is derived from the syntax? 5.6 [expr.mul]: 719: Is unsigned arithmetic modulo 2~N for multiplication as well? +--------+ | Core 3 | +--------+ Templates --------- 14 [temp]: 757: Can a template member function be overloaded? 14.3 [temp.arg]: 758: Can an array name be a template argument? 759: Initializing a template reference parameter with an argument of a derived class type needs to be described 760: Is a template argument that is a private nested type accessible in the template instantiation context? 14.5.1.1 [temp.mem.func]: 761: Can the member function of a class template be virtual? 14.5.5.1 [temp.arg]: 762: How can function template be overloaded? 14.5.5.2 [temp.func.order]: 763: Partial Specialization: the transformation also affects the function return type 14.6 [temp.res]: 736: How can/must typename be used? 764: undeclared name in template definition should be an error 765: The syntax does not allow the keyword 'template' in 'expr.template C' 766: How do template parameter names interfere with names in nested namespace definitions? 14.6.4 [temp.dep.res]: 737: How can dependant names be used in member declarations that appear outside of the class template definition? 14.6.4.1 [temp.point]: 767: Where should the point of instantiation of class templates be discussed? 14.8.2 [temp.deduct]: 677: Should the text on argument deduction be moved to a subclause discussing both function templates and class template partial specializations? 768: typename keyword missing in some examples Exception Handling ------------------ 15.2 [except.dtor]: 769: Are the base class dtors called if the derived dtor throws an exception? ============================================================================= Chapter 1 - Introduction -------------------------- Work Group: Core Issue Number: 604 Title: Should the C++ standard talk about features in C++ prior to 1985? Section: 1.1 [intro.scope] Status: editorial Description: UK issue 229: "Delete the last sentence of 1.1 and Annex C.1.2. This is the first standard for C++, what happened prior to 1985 is not relevant to this document." Resolution: At the Hawaii meeting, the C compatibility WG decided: "Delete references to C.1. Annex C.1 needs to be removed or rewritten." Requestor: UK issue 229 Owner: (C Compatibility) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 602 Title: Are ill-formed programs with non-required diagnostics really necessary? Section: 1.3 [intro.compliance] Status: active Description: UK issue 9: "We believe that current technology now allows many of the non-required diagnostics to be diagnosed without excessive overhead. For example, the use of & on an object of incomplete type, when the complete type has a user-defined operator&(). We would like to see diagnostics for such cases." Question: Do deprecated features render a program ill-formed but no diagnostic is required? See also UK issue 93. Resolution: Requestor: UK issue 9 Owner: Josee Lajoie (Conformance Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 619 Title: Is the definition of "resource limits" needed? Section: 1.3 [intro.compliance] Status: editorial Description: 1.3 para 2 says: "Every conforming C++ implementation shall, within its resource limits, accept and correctly execute well-formed C++ programs..." The term resource limits is not defined anywhere. Is this definition really needed? Resolution: Requestor: ANSI Public comment 7.12 Owner: Josee Lajoie (Conformance Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 603 Title: Do the WP constraints prevent multi-threading implementations? Section: 1.8 [intro.execution] Status: active Description: UK issue 11: "No constraints should be put into the WP that preclude an implementation using multi-threading, where available and appropriate." Bill Gibbons notes: For example, do the requirements on order of destruction between sequence points preclude C++ implementations on multi-threading architectures? Resolution: Requestor: UK issue 11 Owner: Steve Adamczyk (sequence points) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 694 Title: List of full-expressions needed Section: 1.8 [intro.execution] Status: editorial Description: 1.8p14: "certain contexts in C++ cause the evaluation of a full-expression that results from a syntactic construct other than expression" Is it enumerated anywhere exactly what these contexts are? Do the contexts themselves at least identify themselves as surrogate full-expressions? I didn't read the cited example (8.3.6) as thoroughly as I might, but I didn't see anything there that explicitly said "this is treated like a full-expression." Probably you could make the case based on combining several passages together, but if the other ones are like this, it would take some real detective work to figure it out. If someone knows what contexts were intended here, even if something might be omitted, it would be an improvement to make it explicit, either here or in the various contexts. Resolution: Requestor: Mike Miller Owner: Steve Adamczyk (Sequence Points) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 2 - Lexical Conventions --------------------------------- Work Group: Core Issue Number: 744 Title: Is the description of trigraph processing wrong? Section: 2.3[lex.trigraph] Status: active Description: 2.3 para 4 says: "Trigraph replacement is done left to right, so that when two sequences which could represent trigraphs overlap, only the first sequence is replaced. [Example: The sequence "???=" becomes "?=", not "?#". The sequence "?????????" becomes "???", not "?". -- end example]" [Clark Nelson, edit-778:] > A new paragraph was added after the September draft, > specifically [lex.trigraph]/4. The paragraph seems to be > trying to clarify some aspects of trigraph processing. > > Unfortunately, the entire paragraph seems to be based on a > false premise; to wit, that ??? is a trigraph which is > replaced by a single ?. However, ??? is not listed as a > trigraph sequence in the trigraph table, and according to > paragraph 3, there are no other trigraphs. If ??? were > a trigraph for ?, then paragraph 4 would be meaningful and, > arguably, necessary clarification. However, if (as I believe) > ??? is not a trigraph of any sort, then the new paragraph 4 > is actually meaningless and/or just plain wrong, and should be > deleted. > > As a possibly related issue, in the C standard, the statements > of paragraph 3 are normative. Should the note-brackets around > that paragraph be removed from the working paper? If they were, > the confusion about ??? might have been a little less likely. Resolution: Requestor: Clark Nelson Owner: Tom Plum (Lexical Conventions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================ Chapter 3 - Basic Concepts ---------------------------- Work Group: Core Issue Number: 745 Title: Does &inline_function yield the same result in all the translation units? Section: 3.2[basic.def.odr] Status: editorial Description: 3.2 para 4 says: "An inline functions shall be declared in every translation unit in which it is used." It is not clear from this statement whether taking the address of an inline function in different translation units must yield the same result. Resolution: Requestor: Owner: Josee Lajoie (ODR) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 664 Title: When does the reevaluation rule for class scope name lookup require a diagnostic? Section: 3.3.6 [basic.scope.class] Status: editorial Description: 3.3.6 para 1 says: 1) The potential scope of a name declared in a class consists not only of the declarative region following the name's declarator, but also of all function bodies, default arguments, and constructor ctor-initializers in that class (including such things in nested classes). 2) The name N used in a class S shall refer to the same declaration when re-evaluated in its context and in the completed scope of S. 3) If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program's behavior is ill-formed, no diagnostic is required. According to the wording above, a diagnostic is required to be issued for the following program. Should it? typedef int I; //1 class D { typedef I I; //2 }; This is ill-formed according to rule 2) but not according to rule 3) (i.e. this not a reordering problem). Rule 3) is the rule for which "no diagnostic is required." Should Rule 2) also say: "no diagnostic is required."? Otherwise, this will require that an implementation processes class member declarations twice in order to determine if names used by the declaration change meaning. Resolution: Rule 2) was modified to say: "No diagnostic is required for a violation of the rule." The example above should be added to the WP. Requestor: Steve Adamczyk Owner: Josee Lajoie (Name Lookup) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 686 Title: Where is a function name looked up if an argument type is introduced with a typedef or a using-declaration? Section: 3.4.2 [basic.lookup.koenig] Status: editorial Description: basic.lookup.koenig says: When an unqualified name is used as the postfix-expression in a function call (_expr.call_), other namespaces not considered during the usual unqualified look up (_basic.lookup.unqual_) may be searched; this search depends on the types of the arguments. For each argument type T in the function call, there may be a set of zero or more associated namespaces to be considered; such namespaces are determined in the following way: [...] - If T is a class type, its associated namespaces are the namespaces in which the class and its direct and indirect base classes are defined. This text is not very clear as to what happens if the type was introduced with a typedef or a using-declaration: namespace N1 { struct T { }; void f(T); void g(T); }; namespace N2 { using N1::T; typedef N1::T U; void f(T); void g(U); }; void foo() { N2::T t; N2::U u; f(t); // which f? g(u); // which g? } Resolution: The following was added to 3.4.2 paragraph 2: "Typedef names used to specify the types do not contribute to this set." I still think some text should be added to say what happens if the type was introduced with a using declaration. Requestor: Andrew Koenig Owner: Josee Lajoie (Name Lookup) Emails: core-7041 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 665 Title: In X::~Y is Y looked up in the context of the current expression? Section: 3.4.3 [basic.lookup.qual] Status: active Description: In an expression like p->X::~X(); where is the "X" that follows the "~" looked up? 3.4.5 [basic.lookup.classref] says that in an unqualified name, the name after the ~ is looked up in the current context and in the class of p. But it doesn't say anything special about the qualified case. This implies that it is looked up in the scope of X only. If this is true, it seems to me that is a problem because it doesn't work when X is a typedef, as in: struct A { ~A(); }; typedef A AB; int main() { AB *p; p->AB::~AB(); } This suggests that the name after ~ should always be looked up in the current context, even for the qualified name case. Presumably, for the qualified name case it would also be looked up in the class of the qualifier. Resolution: Requestor: John Spicer Owner: Josee Lajoie (Name Look Up) Emails: Papers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 688 Title: Rules for name lookup after :: . -> need to be clarified for conversion-function-id, template argument names and destructor names Section: 3.4.5 [basic.lookup.classref] Status: active Description: How is o a destructor name o an id-expression of a conversion-function-id o a template-id o the name of a template-argument looked up when used following a nested-name-specifier or a class member access operator . or -> . Bill Gibbons provided the following table, which I [Josee] filled up: look in must be look in must be name to surrounding visible what visible expression look up context there ? class there ========== ======= =========== ======= ======= ====== A::b b no --- A yes A::~T T no --- A yes A::Z::~T Z no --- A yes A::Z::~T T no --- A::Z yes A::operator T T no --- A yes A::operator Z::T Z no --- A yes A::operator Z::T T no --- A::Z yes A::C C no --- A yes A::C D yes yes no --- A::X::b b no --- A::X yes A::X::~T T no --- A::X yes A::X::Z::~T Z no --- A::X yes A::X::Z::~T T no --- A::X::Z yes A::X::operator T T no --- A::X yes A::X::operator Z::T Z no --- A::X yes A::X::operator Z::T T no --- A::X::Z yes A::X::C C no --- A::X yes A::X::C D yes yes no --- a.b b no --- A yes a.~T T yes yes A yes s.~T T yes yes --- --- a.operator T T yes yes A yes a.operator Z::T Z yes yes A yes a.operator Z::T T no --- Z yes a.C C no --- A yes a.C D yes yes no --- a.X::b X yes no A no a.X::b b no --- X yes a.X::~T T no --- A::X yes s.X::~T T yes yes --- --- a.X::operator T T no --- A::X yes a.X::operator Z::T Z no --- A::X yes a.X::operator Z::T T no --- A::X::Z yes a.X::C C no --- A::X yes a.X::C D yes yes --- --- where a is an object of class type A where s is an object of scalar type We have to clarify the WP to ensure that the above resolutions are clear. Bill also raises the following issues: * The current rules for lookup of "T" in "a.operator T" break template because "T" must be visible in the class, which is impractical if "T" is a template type parameter. I propose changing the rule so the lookup is in the surrounding context only, as with template-id arguments. * The current rules for lookup of "X" in "a.X::b" break templates because when "T" is a template type argument, the instantiation will fail if some base class of "A" (which might itself be a template type argument) happens to have a typedef or class member "T". This might be fixed as a special case in template name lookup, but I propose the simpler fix of changing the rule so the lookup is in the surrounding context only. Resolution: Requestor: Bill Gibbons Owner: Josee Lajoie (Name Lookup) Emails: core-6969 Papers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 746 Title: What is the order of initialization of a class static data member? Section: 3.6.2[basic.start.init] Status: editorial Description: > On comp.std.c++, jlilley@empathy.com (John Lilley) writes: > The order of construction is determined by the placement of > the *definitions* of the static members, not the > declarations within the containing class. Within a single > translation unit (source file), the static members are > constructed in the order of definition (DWP s3.6.2.1 ). Perhaps it is an oversight, rather than a deliberate omission, but section 3.6.2/1 in the Nov 96 working paper refers to "objects of namespace scope with static storage duration"; it does not mention objects of _class scope_ with static storage duration (i.e. static members). As far as I can tell, the current wording of the draft leaves the order of initialization of static members unspecified. Resolution: Requestor: Fergus Henderson Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 747 Title: The term "static initialization" needs to be defined Section: 3.6.2[basic.start.init] Status: editorial Description: para 2 says: "An implementation is permitted to perform the initialization of an object of namespace scope with static storage duration as a static initialization..." The term 'static initialization' needs to be defined. Resolution: Requestor: Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 621 Title: The terms "same type" need to be defined Section: 3.9 [basic.types] Status: editorial Description: The WP needs to define what it means for two objects/expressions to have the same type. The phrase is used a lot throughout the WP. Requestor: Owner: Steve Adamczyk (Types) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 4 - Standard Conversions ---------------------------------- Work Group: Core Issue Number: 711 Title: Is an lvalue-to-rvalue conversion on an incomplete type allowed within a sizeof operand? Section: 4.1 [conv.lval] Status: editorial Description: 4.1 Paragraph 1 says: "An lvalue ... can be converted to an rvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed." Paragraph 2 says: "When an lvalue-to-rvalue conversion occurs within the operand of sizeof (5.3.3) the value contained in the referenced object is not accessed, since that operator does not evaluate its operand." It isn't entirely clear from this whether it is OK to have an lvalue-to-rvalue conversion on an incomplete type within a sizeof operand. And if we can, what does it mean. In general, the WP is somewhat vague on which restrictions are relaxed in a sizeof operand. Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 712 Title: Should the result value of a floating-point conversion be implementation-defined? Section: 4.8 [conv.double] Status: active Description: 4.8 says for floating-point conversions: If the [floating-point] source value is between two adjacent [floating-point] destination values, the result of the conversion is an unspecified choice of either of those values. yet 2.13.3 says for floating-point literals: the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representatble value, chosen in an implementation-defined manner. Why not say "implementation-defined" for conversions too? This also applies to the integral to floating conversions described in 4.9 [conv.fpint]. Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 5 - Expressions ------------------------- Work Group: Core Issue Number: 748 Title: Should we say that operator precedence is derived from the syntax? Section: 5[expr] Status: editorial Description: para 4: "Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified." "Except where noted" Should we say that operator precedence is derived from the syntax? The C syntax says this in a footnote. (Footnote 35). Resolution: Requestor: Owner: Steve Adamczyk (Expressions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 713 Title: What argument type can be passed to va_arg? Section: 5.2.2 [expr.call] Status: editorial Description: 5.2.2/7 says: "The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the argument expression. After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer to member, or class type, the program is ill-formed." What else can it be? Is this really meaningful? Wouldn't be more explicit to say which argument is _disallowed_. Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 714 Title: Is the term "default argument promotions" needed? Section: 5.2.2 [expr.call] Status: editorial Description: 5.2.2/7 says: "These promotions are referred to as the default argument promotions." This may be the ISO C name, but it is very confusing in C++. It makes one ask, why are only default arguments promoted? Can we use a different name? Steve Adamczyk: > It was added so it could be referenced in the 18.7 > description of va_start, instead of repeating the words, but > that didn't happen. Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 669 Title: semantics for new and delete expressions should be separated from the requirements for operator new and delete Section: 5.3.4 [expr.new], 5.3.5 [expr.delete] Status: editorial Description: Erwin Unruh wrote a paper (96-0011/N0829) that suggested that the semantics for the new expression and the delete expression be reworked so that they would only describe which operator new (or operator delete) they call. The restrictions on the behavior of the allocation and deallocation functions called should be moved to the library section. Subclause 5.3.4[expr.new] and 5.3.5[expr.delete] still has some troublesome passages. 5.3.4 New o Paragraph 8, last sentence says: "The pointer returned by the new-expression is non-null and distinct from the pointer to any other object." The part of this sentence that says "and distinct from the pointer to any other object" should be deleted. This is really a requirement on the library operator new. Maybe a note should be added to say: "If the library allocation function is called, the pointer returned is distinct from the pointer to any other object." o Paragraph 13, first sentence says: "The allocation function shall either return null or a pointer to a block of storage in which space for the object shall have been reserved." This sentence should be moved to the note that follows. Again, this is a requirement that applies to the semantics of the library operator new and should not be in the normative text for 5.3.4. Also paragraph 13 should be moved after paragraph 10, which discusses allocation functions. o Paragraph 16 says: "The allocation function can indicate failure by throwing a bad_alloc exception (_except_, _lib.bad.alloc_). In this case no initialization is done." This should be changed to: "If the allocation function exits by throwing an exception, no initialization is done." o Paragraph 21 says: "The way the object was allocated determines how it is freed: if it is allocated by ::new, then it is freed by ::delete, and if it is an array, it is freed by delete[] or ::delete[] as appropriate." This should be deleted. Name lookup in 5.3.4 and 5.3.5 indicate which operator new and delete is called. 5.3.5 Delete o Paragraph 2, the last few sentences say: "In the first alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object created by a new-expression, or a pointer to a sub-object (_intro.object_) representing a base class of such an object (_class.derived_). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete shall be a pointer to the first element of an array created by a new-expression. If not, the behavior is undefined. [Note: this means that the syntax of the delete-expression must match the type of the object allocated by new, not the syntax of the new-expression.]" The requirements that the object (or array) must be created by a new-expression should be removed. If a user operator delete is called, and this operator does nothing, then all is fine. o Paragraph 7 says: "To free the storage pointed to, the delete-expression will call a deallocation function (_basic.stc.dynamic.deallocation_)." "To free the storage pointed to," should be removed. Again, whether the storage is freed depends on which operator delete is called. A user operator delete may not free the storage. Resolution: Requestor: Erwin Unruh Owner: Josee Lajoie (Memory Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 690 Title: Clarify the lookup of operator new in a new expression Section: 5.3.4 [expr.new] Status: editorial Description: 5.3.4 should describe the lookup of operator new in a new expression. Here is an interesting example: struct C { operator void* new(size_t); operator void* new[](size_t); }; ... new C[N1][N2]; // which operator new is called? Resolution: Requestor: Owner: Josee Lajoie (Memory Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 718 Title: Conversion to and from pointers to incomplete class types using old style casts - is this really unspecified? Section: 5.4 [expr.cast] Status: active Description: p6 describes conversions to and from pointer to incomplete class type and it says: "whether the static_cast or reinterpret_cast interpretation is used is unspecified." Since static_cast does not allow incomplete types, does this mean that it's unspecified whether old-style casts allow conversion between pointers to incomplete types? Mike believes this should not be left unspecified but should be clearly specified by the standard as being ill-formed; i.e. the static_cast interpretation is chosen. Resolution: Requestor: Mike Miller Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 719 Title: Is unsigned arithmetic modulo 2~N for multiplication as well? Section: 5.6 [expr.mul] Status: editorial Description: 5.6/3, Binary * operator According to 3.9.1/3, unsigned arithmetic is always modulo 2^N. For addition and subtraction this is easy to remember, but for multiplication the rule should probably be repeated here since it is less obvious. Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 720 Title: Can you do &*p if p does not point to a valid object? Section: 5.7 [expr.add] Status: active Description: 5.7p5: "If the result is used as an operand of the unary * operator, the behavior is undefined unless both the pointer operand and the result point to elements of the same array object, or the pointer operand points one past the last element of an array object and the result points to an element of the same array object, or the pointer operand points to the element of an array and the result points one past the last element of the same array." Mike Miller proposes to remove this wording. He says: > All the cases described as giving undefined behavior if the > result is used as the operand of unary * are already undefined > behavior according the preceding sentence, regardless of how > the result is used. Bill Gibbons: > Yes, but there still needs to be some editorial work here. > There should be a description of how a "one past the end" > pointer can be used. > > For example: > > void f() { > int x[3]; > int *p = x + 3; > int &rx = *p; // defined behavior? > int y = rx[-1]; > } > > There have been some changes in the last year which allow the > limited use of an lvalue for an incomplete object type. There > are at least three related situations for valid pointers which > do not refer to objects of the pointed-to type: > > * "(*p)", where "p" points just past the end of an array > > * "(*p)", where "p" points to zero-length array as in "p = > new int[n]" when "n" is zero. This is a variation > of the above, since the start of the array and the > "just past the end" point are the same. > > * "(*p)", where p is zero. > > Consider each of these in the context of "q = &*p". > > I think the first two should have the expected defined > behavior. The last case is questionable, but there may be > good reason to allow it. > > The current WP already supports 99% of this proposal. > > The following example is now well-formed, even if "q" is > initialized before "x": > > // translation unit #1 > extern int p; > int *q = &*p; > > // translation unit #2 > int f(); > int x = f(); > int *p = &x; > > So we have the concept of an lvalue which refers to raw > memory, suitably aligned, where the lvalue can be manipulated > as long as the uninitialized value is never used. > > (A similar example could be constructed using a direct call > to operator new and a deferred call to placement new > "new (p) int" where the raw memory does not have a type > explicitly associated with it.) > > Since a pointer to the end of an array is suitable aligned, > the memory and object models almost support the proposal > today. > > The only difference is whether it is required that a block of > raw memory to which an lvalue refers (but does not access), > and the address of which is a valid pointer, must actually > exist. > > (Plus the smaller question of whether it is valid for two > objects to overlap if one of them is never initialized or > accessed, since the address range of the implicit extra array > element may overlap another object.) > > The general rule that I would like is: > > Any pointer containing a valid value may be dereferenced. > If the resulting lvalue is used in a way which requires a > complete type, and the pointer does not actually refer to > an object, the behavior is undefined. [footnote - a > pointer may be valid and yet not refer to an object, e.g. a > pointer to just past the end of an array.] > > Since this would allow "&*(char*)0", it would require > additional wording to prohibit using null pointers this way. Resolution: Requestor: Bill Gibbons Owner: Josee Lajoie (Memory Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 721 Title: Comparisons of pointer to class members need fine tuning Section: 5.9 [expr.rel] Status: editorial Description: 5.9/2 says: "If two pointers point to nonstatic data members of the same object, the pointer to the later declared member compares greater provided the two members are not separated by an access-specifier label (11.1) and provided their class is not a union." The "point to" provision probably should also cover "point within". And the case of pointing just past the end of a member array should be mentioned; it is sufficiently difficult to handle correctly that I think it is OK just to say that this case is unspecified. Resolution: Requestor: Bill Gibbons Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 722 Title: The definition of address constant expression needs fine tuning Section: 5.19 [expr.const] Status: editorial Description: 5.19/4 address constant expressions This needs work. For example, the phrase "The subscription operator ... can be used" does not describe how it may be used; presumably the subscript must be an integral constant expression. The same goes for 5.19/5. Resolution: Requestor: Bill Gibbons Owner: Josee Lajoie (Initialization) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 6 - Statements ------------------------ ============================================================================= Chapter 7 - Declarations -------------------------- Work Group: Core Issue Number: 683 Title: What is the underlying type of an enumeration type if the value of an enumerator uses the value of a previous enumerator? Section: 7.2 [dcl.enum] Status: active Description: There is a small omission in the description of the constant-expression which is used to set an enumerator's value, e.g. enum A { a, b = a + 2 ); // expression "a + 2" The type of "a" in "a+2" presumably follows the usual expression rules. But these rules say, in 4.5/2: An rvalue of type wchar_t (3.9.1) or an enumeration type (7.2) can be converted to an rvalue of the first of the following types that can represent all the values of its underlying type: int, unsigned int, long, or unsigned long. So the evaluation of "a+2" depends on the underlying type of "A", which in turn depends on the value of "b", which depends on the value of "a+2". Although this is unlikely to affect real programs in practice, we should fix the definition. There are cases where it matters, e.g.: // Assume an environment where "int" is 16 bits, just for // convenience (The same problem occurs when "int" is larger. // Think of systems where "int" is 32 bits and "long" is 64 // bits.) enum A { a = 1, b = a-2, c = 32768U }; If we assume the underlying type will be "int", then b is -1 and the actual underlying type is "long". If we assume the underlying type will be "unsigned int", then b is 65535 and the actual underlying type is "unsigned int". The answer may seem obvious, but consider: enum A { a = 1U, b = a-2, c = -1 }; The underlying type will clearly be signed. Does "b" have the value "-1" or is the code ill-formed? There seem to be several possible solutions to this problem: 1) When an enumerator is used in the defining expression of a subsequent enumerator in the same enumeration, its type is the type of its defining expression (where the default defining expression is "previous-enumerator + 1" except the first one, where it is "0"). 2) Give enumerations an "interim" underlying type which is recomputed after each enumerator, and use that underlying type in subsequent defining expressions. 3) Require that enumerator computation be done with an infinite number of bits - assuming that the "as if" rule makes this practical. 4) Say that if the value of a definining expression depends on the underlying type of the enumeration, the program is ill-formed. Bill Gibbons' preference is (1). Bill doesn't think it matters much what the answer is, but the should be described by the working paper. A related problem occurs with the implicit "next value" rule: enum B { a = 32767, b }; Is the code well-formed? If so, what is the underlying type? Why? This example would be fixed if solution (3) was adopted. Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Types) Emails: core-6989 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 672 Title: using-declarations and base class assignment operators Section: 7.3.3 [namespace.udecl] Status: editorial Description: 7.3.3 should indicate what happens if a using-declaration refers to a base class assignment operator and the type of this assignment operator corresponds to the type of the derived class copy assignment operator. struct B; struct A { B& operator=(const B&); }; struct B : A { // introduces B's copy-assignment operator using A::operator=; }; Resolution: At the Hawaii meeting, members of the core WG wanted the implicit copy assignment operator for class B still be generated. The WP should be clarified to say this. Requestor: Bill Gibbons Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 729 Title: Must extern "C" functions declared in a namespace and a global extern "C" function have different signatures and return types? Section: 7.5 [dcl.link] Status: editorial Description: extern "C" int f(int); namespace NS { extern "C" void f(int); // ill-formed? undefined behavior? } Resolution: At the Hawaii meeting, the Core WG agreed that two function declarations referring to the same entity must have the same type. The case above should be made clearer in the WP. Requestor: Owner: Josee Lajoie (extern "C") Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 749 Title: Can a declaration specify both a storage class and a linkage specification? Section: 7.5[dcl.link] Status: active Description: What is the meaning of: extern "C" static void f(); Is this still illegal? Or does it declare a function with C language linkage that is local to the translation unit? Mike Anderson proposes the following: (1) either the WP should indicate that using a storage class in a declaration with a linkage specification with no braces is disallowed; or else, (2) it should indicate at least that the semantics are equivalent whether or not the braces are present and possibly do a bit more to specify what the semantics are. [Josee:] 7.5 para 7 says: "the form of the linkage-specification directly containing a single declaration is treated as an extern specifier for the purpose of determining whether the contained declaration is a definition. extern "C" int i; // declaration " I believe this implies that the declaration above is equivalent to: extern static void f(); and that Mike's solution (1) is the correct one. Resolution: Requestor: Mike Anderson Owner: Josee Lajoie (extern "C") Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 750 Title: To which declarator in a member function declaration does the extern "C" specifier apply? Section: 7.5[dcl.link] Status: editorial Description: [Mike Miller in core-7322]: > What is the meaning of 7.5p4, "A non-C++ language linkage is > ignored ... for the function type of class member function > declarators" with respect to parameters of member functions? > For instance, > > extern "C" { > struct S { > void f(void(*)()); > }; > } > > Does S::f take a "C" function or a "C++" function? The > example in the text deals with related issues but not this > specific one, and the normative text could be read either way, > depending on whether you understand "function type of class > member function declarators" in a shallow or deep sense. [Mike Anderson in core-7323:] I believe it was intended to be understood in a shallow sense (and that S::f takes a "C" function). The words were crafted to make the rule apply only to certain function types (namely, those of member function declarators) and not to any other function types such as the types of function parameters. Would it be sufficient to expand the example to make this clear, or does the normative text need to modified? I think another example would be enough. [Mike Miller in core-7325:] Assuming that we do intend the "shallow" interpretation, I think the normative words there are wrong; the type of S::f is different ("function taking pointer to C function...") from what it would be if it were not inside extern C ("function taking pointer to C++ function..."), i.e., the non-C++ linkage is *not* ignored in determining the function type. IMHO, it should be rewritten to read something like, "The language linkage of member names and member function types is C++, regardless of the linkage specification in which the class may be defined." (An example is also a good idea.) Resolution: Requestor: Mike Miller Owner: Josee Lajoie (extern "C") Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 8 - Declarators ------------------------- Work Group: Core Issue Number: 689 Title: What if two using-declarations refer to the same function but the declarations introduce different default-arguments? Section: 8.3.6 [dcl.fct.default] Status: editorial Description: 7.3.3 para 10 says: "If the set of declarations and using-declarations for a single name are given in a declarative region, -- they shall all refer to the same entity, or all refer to functions; or ..." 8.3.6 para 9 says: "When a declaration of a function is introduced by way of a using declaration, any default argument information associated with the declaration is imported as well." This is not really clear regarding what happens in the following case: namespace A { extern "C" void f(int = 5); } namespace B { extern "C" void f(int = 7); } using A::f; using B::f; f(); // ??? Resolution: At the Hawaii meeting, the core WG agreed that the example above was an error and suggested that this be clarified in the WP as an editorial matter. Requestor: Bill Gibbons Owner: Josee Lajoie (Default Arguments) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 730 Title: When are default arguments for member functions of template classes semantically checked? Section: 8.3.6 [dcl.fct.default] Status: active Description: para 5: "The names in the expression are bound and the semantic constraints are checked at the point of declaration." template class Cont { // ... public: Cont(const T& default_element = T()); // ... }; class Y { public: Y(int); // ... no Y() ... }; Cont y1; // error: no Y() (that's fine) Cont y2(Y(99)); // use 99 as default value However, is the last declaration legal? When is the checking of the T() for Cont done? The current WP implies that it is checked when C is first instantiated. If this is the case, all of the standard containers are badly broken - it is not possible to have container with elements of a type without a default constructor. Bjarne's Proposed Resolution: The default argument resolution from Stockholm broke the library and should be revised. I suspect that treating a default argument like the return type for an operator->() and the definition of a template member function is the right way (check if and when the default argument is used) and for the same reason: For ordinary classes it makes sense to check when you see the class, for templates that is seriously constraining. Mike Miller's Proposed Resolution: The semantic constraints on a default argument should be checked on use, not on declaration, for normal functions as well as template functions. C++ has a number of cases where you can declare things that you cannot use because of unresolvable ambiguities, but we have chosen to diagnose them on use, not on declaration. The rationale for this choice is that diagnosis on declaration prevents composing classes from disparate sources, even though the composition might be useful in ways that do not stumble over the ambiguity. Mike thinks default arguments are a similar situation -- the function is completely usable as long as you don't rely on the problematic portion of the declaration. While templates are the most likely context in which this issue might arise, I believe there are probably others in non-template situations. Mike would support a reconsideration of the "immediate diagnosis" part of the Stockholm resolution, preferably altogether, although applying the revision just to templates would still be an improvement. Resolution: Requestor: Bjarne Stroustrup Owner: Steve Adamczyk (Default Arguments) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 751 Title: Should { } be allowed around an initializer that is a string? Section: 8.5[dcl.init] Status: active Description: The current WP disallows: const char a[3] = {"asdf"}; However, this is allowed in C. 8.5 paragraph 13 says: "If T is a scalar type, then ... T x = { a }; is equivalent to T x = a; " An array is not a scalar type. If the committee decides to leave things the way they are, this difference between C and C++ should be listed in appendix C. Resolution: Requestor: Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 9 - Classes --------------------- Work Group: Core Issue Number: 692 Title: ";opt" after member "function-definition" should be omitted Section: 9.2 [class.mem] Status: editorial Description: The syntax says: member-declaration: ... function-definition ;opt ";opt" should be omitted. Otherwise, the syntax is ambiguous. Resolution: Requestor: Owner: (Syntax) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 505 Title: Must anonymous unions declared in unnamed namespaces also be declared static? Section: 9.5 [class.union] Unions Status: active Description: 9.5p3 says: "Anonymous unions declared at namespace scope shall be declared static." Must anonymous unions declared in unnamed namespaces also be declared static? If the use of static is deprecated, this doesn't make much sense. Proposal: Replace the sentence above with the following: "Anonymous unions declared in a named namespace or in the global namespace shall be declared static." This is related to issue 526. Resolution: Requestor: Bill Gibbons Owner: Josee Lajoie (linkage) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 10 - Derived classes ------------------------------ Work Group: Core Issue Number: 624 Title: class with direct and indirect class of the same type: how can the base class members be referred to? Sections: 10.1 [class.mi] Multiple base classes Status: editorial Description: para 3 says: "[Note: a class can be an indirect base class more than once and can be a direct and indirect base class.]" The WP should describe how base class members can be referred to, how conversion to the base class type is performed, how initialization of these base class subobjects takes place. Resolution: At the Stockholm meeting, the core 1 WG decided to handle this as an editorial issue. A note will be added to the WP to clarify the restrictions on accessing members of the direct base class. Requestor: Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 11 - Member Access Control ------------------------------------ Work Group: Core Issue Number:a 752 Title: When accessing a base class member, the qualification is not ignored Section: 11.5[class.protected] Status: editorial Description: 11.2 para 4 says: "The access to a member is affected by the class in which the member is named. This naming class is the class in which the member name was looked up and found. [Note: this class can be explicit, e.g., when a qualified-id is used, or implicit, e.g., when a class member access operator (_expr.ref_) is used (including cases where an implicit this->" is added. If both a class member access operator and a qualified-id are used to name the member (as in p->T::m), the class naming the member is the class named by the nested-name-specifier of the qualified-id (that is, T). ]" This is contradictory to the example in 11.5 para 1: class B { protected: int i; static int j; }; class D1 : public B { }; class D2 : public B { friend void fr(B*,D1*,D2*); void mem(B*,D1*); }; void fr(B* pb, D1* p1, D2* p2) { p2->B::i = 4; // ok (access through a D2, // *** qualification ignored *** } According to 11.2 para 4, the qualification is not ignored. Resolution: Requestor: Owner: Steve Adamczyk (Access) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 12 - Special Member functions --------------------------------------- Work Group: Core Issue Number: 753 Title: Is 'new char[size]' aligned properly to hold an object of any type T? Section: 12.4[class.dtor] Status: active Description: [Fergus Henderson in core-7251:] > The following example in a note in 12.4/13 is not strictly > conforming C++ according to the rules defined elsewhere in the > draft. I think it should be changed. > > "13[Note: explicit calls of destructors are rarely needed. One > use of such calls is for objects placed at specific addresses > using a new- expression with the placement option. Such use > of explicit placement and destruction of objects can be > necessary to cope with dedicated hardware resources and for > writing memory management facilities. For example, > void* operator new(size_t, void* p) { return p; } > struct X { > // ... > X(int); > ~X(); > }; > void f(X* p); > > void g() // rare, specialized use: > { > char* buf = new char[sizeof(X)]; > X* p = new(buf) X(222); // use buf[] and initialize > f(p); > p->X::~X(); // cleanup > } > --end note] > " > > The lines > > char* buf = new char[sizeof(X)]; > X* p = new(buf) X(222); // use buf[] and initialize > > are not strictly conforming, because there is no guarantee > that `buf' will be sufficiently aligned to hold an object of > type `X'. 5.3.4[expr.new]/12 includes some examples which > show that this is not guaranteed. I think the first of those > lines should be changed to > > char* bug = ::operator new(sizeof(X)); > > For stylistic reasons, it might also be a good idea to change > the line > > p->X::~X(); // cleanup > > to just > > p->~X(); [Mike Miller in core-7257:] > Yes, you're right -- there's no requirement that the "array > allocation overhead" is a multiple of the maximum alignment > requirement, so the example you cited is not guaranteed to > work by the current WP text. > > However, there's a reason this example is in the WP, and it's > because this is a very common idiom. I don't see a compelling > reason to break it. > > I can see three possibilities for accommodating the use of > "new char[xx]" to get a suitably-aligned buffer space for other > objects: > 1) require that the "array allocation overhead" be an > integral multiple of the maximum alignment requirement, and > that it be required to be a contiguous region between the > pointer returned by operator new[] and the pointer to the > first element of the array. > 2) Allow "array allocation overhead" only for arrays of class > types (my understanding of the reason for the overhead is > to allow the correct invocation of destructors). > 3) Make char and unsigned char a special case, like they are > in many other ways, such that allocating an array of char > or unsigned char is guaranteed to have an "array allocation > overhead" of zero. > I guess I don't have a strong preference among the three, > although 2 and 3 seem a bit more straightforward and > correspond more to the rest of the language. > > This is obviously not a make-or-break issue; people will > continue to write "new char[xx]" and it will continue to work, > whether we bless it or not. But it's not hard to change the > WP to allow it, and it would bring us a little closer to > reality to recognize this particular practice. Resolution: Requestor: Fergus Henderson Owner: Josee Lajoie (Memory Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 754 Title: for new T, allocation functions in base classes of T are not considered Section: 12.5[class.free] Status: editorial Description: 12.5 para 2 says: "When a new-expression is used to create an object of class T (or array thereof), the allocation function is looked up in the scope of class T; if no allocation function is found, the global allocation function is used." It should be made clearer that allocation functions in base classes are not considered. Resolution: Requestor: Dan Saks Owner: Josee Lajoie (Memory Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 687 Title: The WP prohobits the copy assignment of virtual base classes to behave like the copy constructor Section: 12.8 [class.copy] Status: active Description: The ARM specified: "Objects representing virtual base classes will be assigned only once by a generated assignment operator." This restriction has been removed. The current WP says in 12.8 para 13: "The direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list, and then the immediate nonstatic data members of X are assigned, in the order in which they were declared in the class definition. [...] It is unspecified whether subobjects representing virtual base classes are assigned more than once by the implicitlys-defined copy assignment operator." The new specification does not allow the copy constructor ordering. Resolution: Requestor: Bill Gibbons Owner: Josee Lajoie (Object Model) Emails: Papers: 96-0107/N0925 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 755 Title: Assignment of POD class objects: is the class copied as a block? Section: 12.8[class.copy] Status: editorial Description: [ Tom MacDonald compat-353:] > Recently I became aware of an incompatibility between C and C++ > > Consider the following example: > > struct S_Pair; > > typedef struct Object { > struct S_Pair *addr; > int tag; > } Object; > > struct S_Pair { > Object car; > Object cdr; > }; > > Object x; > > void copy_it(void) { > > x = x.addr->cdr; > > } > > The C++ rules permit the following implementation of the > structure assignment inside the function copy_it. > > x.addr = x.addr -> cdr.addr; > x.tag = x.addr -> cdr.tag; > > The C rules are more strict as indicated in 6.3.16.1, the > first paragraph under Semantics says: > > In simple assignment(=), the value of the right operand is > converted to the type of the assignment expression and > replaces the value stored in the object designated by the left > operand. > > Note that the value is spoken of as a whole. There appears > to be nothing that allows the identity of the right operand to > change in the middle of the assignment, which is the effect > what the C++ rules permit. > > The second paragraph under Semantics forbids partial overlap. > This allows a more efficient implementation of a structure > assignment (between lvalues) as > > memcpy(&left_operand, &right_operand) > > or an inline equivalent, rather than as > > memmove(&left_operand, &right_operand) > > which would include the extra work needed to accommodate the > possibility of partial overlap (such as copying through a > temporary object, or deciding whether to copy bytes from the > beginning or from the end). Note that in either case, the > addresses of the two operands are computed before the copying > begins. > > The following implementation produces the expected C behavior. > > { > Object * tmp = &(x.addr->cdr); > x.addr = tmp->data; > x.tag = tmp->tag; > } It was not the intention of the C++ standards committee to make C++ different from C in this case. How could the WP be clarified to make this intent clearer? Resolution: Requestor: Tom MacDonald (C compatibility) Owner: Josee Lajoie (Memory Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 13 - Overloading -------------------------- Work Group: Core Issue Number: 733 Title: Implicit conversion sequences and scalar types Section: 13.3.3.1 [over.best.ics] Status: editorial Description: 13.3.3.1 para 6: "The implicit conversion sequence is the one required to convert the argument expression to an rvalue of the type of the parameter. ... When the parameter has a class type and the argument expression is an ravlue of the same type, the implicit conversion sequence is identity conversion. When a parameter has class type and the argument expression is an lvalue of the same type, the implicit conversion sequence is an lvalue-to-rvalue conversion." Shouldn't the last two sentences also apply to non-class types? Jason Merrill also notes in core-7309: > In this test case, I assert that under the current overloading > rules the second and third functions are equally good matches for > the argument, even though the third is "obviously" the right > choice. The ics for the third a reference binding to the lvalue, > while the ics for the second is a reference binding to a temporary, > but that also has identity rank because there are no lvalue->rvalue > conversions for built-in types. Perhaps there should be? > > int f(char &); > int f(const char &); > int f(volatile char &); > int f(const volatile char &); > > int main() > { > volatile char c = 'a'; > f (c); > } To which Stephen Adamczyk replies: > I believe there are lvalue-to-rvalue conversions for builtin types. > Perhaps you're interpreting 13.3.3.1 para 6 (over.best.ics) as > saying there aren't, because it mentions them explicitly for class > types but not for builtin types. > But the class wording is needed because it is a special case. For > builtin types, the lvalue-to-rvalue conversion is a normal part of > the implicit conversion sequence, and as 13.3.3.1.1 (over.ics.scs) > says, that includes an lvalue-to-rvalue conversion when > appropriate. [Josee:] I think a note or footnote should be added to make this clear. I have seen a few compiler writers trip over this. Resolution: Requestor: Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 682 Title: operator ?: and operands of enumeration types Section: 13.6 [over.built] Status: active Description: The type of a conditional expression choosing between two enums of the same type was changed in the May WP from that enum type to the integral type it promotes to, breaking code. I propose changing paragraph 27 of 13.6 [over.built] from 27 For every type T, where T is a pointer or pointer-to-member type, there exist candidate operator functions of the form T operator?(bool, T, T); to 27 For every type T, where T is an enumeration, pointer or pointer-to-member type, there exist candidate operator functions of the form T operator?(bool, T, T); ---------- Should the following testcase be ambiguous? const char c; enum E { a } e; bool b; main () { return b ? c : e; } The builtin candidates are: operator ?(bool, const char &, const char &) operator ?(bool, int, int) Resolution: Requestor: Jason Merrill Owner: Steve Adamczyk (Type Conversions) Emails: core-6983, core-6987 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 734 Title: ambiguity in "bool & ? void *& : classType&" where classType has an operator void*& Section: 13.6 [over.built] Status: active Description: This testcase is ambiguous under the current rules: void *p; struct A { operator void*& () { return p; }; }; bool b; A a; main () { void *q = b ? p : a; } The implementation of the current rules results in: Ambiguous overload for `bool & ? void *& : A &' candidates are: operator ?:(bool, void *&, void *&) operator ?:(bool, void *, void *) because there is no lvalue->rvalue conversion to disambiguate for non-class operands. Resolution: Requestor: Jason Merrill Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 756 Title: most uses of built-in "?" with class operands are ambiguous Section: 13.6[over.built] Status: active Description: The pseudo-prototype for the "?" operator in [over.built] makes most uses of "?" with a class operand ambiguous. Consider struct A {}; struct B { operator A(); }; void f() { A a; B b; 1 ? a : b; } The pseudo-prototype generates the following (and more, but these are enough to demonstrate the ambiguity): bool ? A : A bool ? const A : const A These are indistinguishable in overload resolution, in the same way that void g(A); void g(const A); are indistinguishable. As [over.best.ics] para 6 says, in a copy-initialization, "Any difference in top-level cv-qualification is subsumed by the initialization itself and does not constitute a conversion." Resolution: Requestor: Steve Adamczyk Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 14 - Templates ------------------------ Work Group: Core Issue Number: 757 Title: Can a template member function be overloaded? Section: 14[temp] Status: editorial Description: 14 paragraph 5 says: "The name of a class template shall not be declared to refer to any other template, class, function, object, enumeration, enumerator, namespace, or type in the same scope (_basic.scope_). Except that a function template can be overloaded either by (non-template) functions with the same name or by other function templates with the same name (_temp.over_), a template name declared in namespace scope shall be unique in that namespace." This paragraph forgets to say that (except for overloading) the name of a function template in class scope must not be the same as the name of any other class member. Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 758 Title: Can an array name be a template argument? Section: 14.3[temp.arg] Status: editorial Description: 14.3[temp.arg] para 3 says: "A template-argument for a non-type non-reference template-parameter shall be ... the address of an object or a function with external linkage ... The address of an object or function shall be expressed as &f, plain f (for function only) ..." It is followed by the following example: char p[] = "Vivisectionist"; X x2; // & is not used i.e. the array name is not preceded with the & operator. What was probably intended is the following: "The address of an object or function shall be expressed as '&e' except when 'e' is a function or an array in which case it can be expressed as 'e'." Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 759 Title: Initializing a template reference parameter with an argument of a derived class type needs to be described Section: 14.3[temp.arg] Status: editorial Description: 14.3[temp.arg], paragraph 6: "Standard conversions (_conv_) are applied to an expression used as a template-argument for a non-type template-parameter to bring it to the type of its corresponding template-parameter. [Example: struct Base { /* ... */ }; struct Derived : Base { /* ... */ }; template struct Y { /* ... */ }; Derived d; Y yd; // derived to base conversion -- end example] " Since binding an object of a derived class type to a reference to a base class type is not a standard conversion anymore, this text needs work. Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 760 Title: Is a template argument that is a private nested type accessible in the template instantiation context? Section: 14.3[temp.arg] Status: active Description: Sean Corfield in core-7317: Is the private nested class accessible in the instantiation context? class Outer { //... private: class Inner { //... }; list< Inner > data; }; Since Outer::Inner is inaccessible outside the scope of Outer and its friends, one can imagine that instantiations would fail. A quick trial on the local compiler agrees (HP's Cfront -- not much of a yardstick). 14.3 [temp.arg] says: 10For a template-argument of class type, the template definition has no special access rights to the inaccessible members of the template argument type. The name of a template-argument shall be accessible at the point where it is used as a template-argument. All that says is that inaccessible *members* can't be accessed. Is it *really* intending to say that if a template argument is accessible "at the point where it is used as a template-argument" then any & all uses of the corresponding template parameter are accessible within the template body? // Outer::Inner as before template void A::f() { T t; // same as Outer::Inner t but Outer::Inner is not // accessible } I believe we intend that to be well-formed but I just don't think the WP is quite clear enough about it (and certainly some compilers disagree). Resolution: Requestor: Sean Corfield Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 761 Title: Can the member function of a class template be virtual? Section: 14.5.1.1[temp.mem.func] Status: editorial Description: 14.5.1.1 paragraph 3 says: "A member function of a class template is implicitly a member function template with the template-parameters of its class template as its template-parameters." 14.5.2 paragraph 3 says: "A member function template shall not be virtual." This seems to imply that virtual member functions in a class template are ill-formed. template struct AA { virtual void f(); // this is an error }; It should be clarified to say that the following is an error. template struct AA { template virtual void f(C); // this is an error }; We should get rid of the wording in 14.5.1.1 that says that a member function of a class template is a member function template with the template parameters of its class. This sentence is confusing. Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 762 Title: How can function template be overloaded? Section: 14.5.5.1[temp.arg] Status: editorial Description: 14.5.5.1 para 4 says: "The signature of a function template consists of its function signature, its return type and its template parameter list. The names of the template parameters are significant only for establishing the relationship between the template parameters and the rest of the signature." I think an example showing that two function templates that have the same function parameter list are valid overloads would make it clear that such thing is allowed. For example: template void f(); template void f(); // valid overload Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 763 Title: Partial Specialization: the transformation also affects the function return type Section: 14.5.5.2[temp.func.order] Status: editorial Description: 14.5.5.2 [temp.func.order] paragraph 2 says: "The transformation used is: -- For each type template parameter, synthesize a unique type and substitute that for each occurrence of that parameter in the function parameter list. -- For each non-type template parameter, synthesize a unique value of the appropriate type and substitute that for each occurrence of that parameter in the function parameter list." These bullets should say: "... in the function parameter list _and return type_". Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 736 Title: How can/must typename be used? Section: 14.6 [temp.res] Status: active Description: Is typename required in situations where we know only type names can be used? class typename T::X var; // or class T::X var; ? Other situations: o base class names o before :: o operator typename T::X or operator T::X ? o dynamic_cast or dynamic_cast ? --------------------------- What if typename is used preceding a template dependent name that is not qualified? Is typename ignored, or is this ill-formed? template class C { typename C ... }; --------------------------- What if typename is used preceding an non-dependant name? Is typename ignored, or is this ill-formed? class A { }; template class C { typename A ... }; --------------------------- Is the following well formed? template class A { }; It is not totally clear how typename can be used in a template parameter list. --------------------------- The WP needs to be clearer about these cases. Resolution: Requestor: Owner: Bill Gibbons/John Spicer (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 764 Title: undeclared name in template definition should be an error Section: 14.6[temp.names] Status: editorial Description: The example in 14.6 paragraph 1 has the following lines: T::A* a7;// T::A is not a type name: // multiply T::A by a7 B* a8; // B is not a type name: // multiply B by a8; ill-formed, // no visible declaration of B The first line is also ill-formed because a7 is not declared. Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 765 Title: The syntax does not allow the keyword 'template' in 'expr.template C' Section: 14.6[temp.names] Status: editorial Description: In 14.2[temp.names], paragraph 4 says: "When the name of a member template specialization appears after . or -> in a postfix-expression, or after :: in a qualified-id that explicitly depends on a template-argument (_temp.dep_), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template." The grammar in 14.6 paragraph 2 does not seem to take this into account: elaborated-type-specifier: . . . typename ::(opt) nested-name-specifier identifier typename ::(opt) nested-name-specifier identifier < template-argument-list > shouldn't this say? elaborated-type-specifier: . . . typename ::(opt) nested-name-specifier template(opt) identifier typename ::(opt) nested-name-specifier template(opt) identifier < template-argument-list > Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 766 Title: How do template parameter names interfere with names in nested namespace definitions? Section: 14.6.1[temp.local] Status: active Description: 14.6.1[temp.local] paragraph 6 says: "In the definition of a member of a class template that appears outside of the class template definition, the name of a member of this template hides the name of a template-parameter. [Example: template struct A { struct B { /* ... */ }; void f(); }; template void A::f() { B b; // A's B, not the template parameter } -- end example] " This does not cover namespaces very well. For example, what happens when a template parameter names conflicts with the name of a namespace member. namespace N { struct B { /* ... */ }; template void f(T); } template void N::f(B) { B b; // A's B or the template parameter? } John Spicer's proposed resolution: You should get the same result whether the function is defined in the class (or namespace) or outside of it. The "B" in N::f gets the template parameter B, not the namespace member B. Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 737 Title: How can dependant names be used in member declarations that appear outside of the class template definition? Section: 14.6.4 [temp.dep.res] Status: editorial Description: template class Foo { public: typedef int Bar; Bar f(); }; template typename Foo::Bar Foo::f() { return 1;} -------------------- In the class template definition, the declaration of the member function is interpreted as: int Foo::f(); In the definition of the member function that appears outside of the class template, the return type is not known until the member function is instantiated. Must the return type of the member function be known when this out-of-line definition is seen (in which case the definition above is ill-formed)? Or is it OK to wait until the member function is instantiated to see if the type of the return type matches the return type in the class template definition (in which case the definition above is well-formed)? From John Spicer: > My opinion (which I think matches several posted on the > reflector recently) is that the out-of-class definition must > match the declaration in the template. In your example they > do match, so it is well formed. > > I've added some additional cases that illustrate cases that > I think either are allowed or should be allowed, and some > cases that I don't think are allowed. > > template class A { typedef int X; }; > > template class Foo { > public: > typedef int Bar; > typedef typename A::X X; > Bar f(); > int g1(); > Bar g2(); > X h(); > X i(); > int j(); > }; > > // Declarations that are okay > template typename Foo::Bar Foo::f() > { return 1;} > template typename Foo::Bar Foo::g1() > { return 1;} > template int Foo::g2() { return 1;} > template typename Foo::X Foo::h() { return 1;} > > // Declarations that are not okay > template int Foo::i() { return 1;} > template typename Foo::X Foo::j() { return 1;} > > In general, if you can match the declarations up using only > information from the template, then the declaration is valid. > > Declarations like Foo::i and Foo::j are invalid because for > a given instance of A, A::X may not actually be int if > the class is specialized. > > This is not a problem for Foo::g1 and Foo::g2 because for > any instance of Foo that is generated from the template > you know that Bar will always be int. If an instance of Foo > is specialized, the template member definitions are not used > so it doesn't matter whether a specialization defines Bar as > int or not. Resolution: Core 3 agreed that this is largely editorial. Some work is needed to figure out exactly what needs to be said. Owner: Bill Gibbons/John Spicer (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 767 Title: Where should the point of instantiation of class templates be discussed? Section: 14.6.4.1[temp.point] Status: editorial Description: 14.6.4.1[temp.point]: Shouldn't this subclause also discuss the point of instantiation of class templates? 14.7.1 covers some aspect of the point of instantiation of class templates. Having a subclause called "point of instantiation" and only discuss function templates within it is somewhat confusing. Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 677 Title: Should the text on argument deduction be moved to a subclause discussing both function templates and class template partial specializations? Section: 14.8.2 [temp.deduct] Status: editorial Description: Template argument deduction is now used both for function templates and for class template partial specializations. The text for temp.deduct should be moved out of the function template specializations subclause. Here is the reorganization Bill Gibbons suggested in private email: > 14.2 Names of template specializations (including functions) > 14.3 Template arguments (including functions; cross-ref arg > deduction) > ... > 14.8 Template argument deduction > 14.8.1 Deducing a template argument from an expression > 14.8.2 Argument deduction for function calls > 14.8.3 Argument deduction for partial specialization ordering > > 14.9 Function calls > 14.9.1 Mixing explicit and deduced template arguments > 14.9.2 Overload resolution > 14.9.3 Overloading and template specializations Resolution: Requestor: Sean Corfield Owner: Bill Gibbons/John Spicer (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 768 Title: typename keyword missing in some examples Section: 14.8.2[temp.deduct] Status: editorial Description: 14.8.2 paragraph 10 is an error template T deduce(A::X x, // T is not deduced here T t, // but T is deduced here B::Y y); // i is not deduced here A a; B<77> b; int x = deduce<77>(a.xm, 62, y.ym); // T is deduced to be int, a.xm must be convertible to // A::X // i is explicitly specified to be 77, y.ym must be convertible // to B<77>::Y According to 14.6 paragraph 2 "A qualified-name that refers to a type and that depends on a template-parameter shall be prefixed by the keyword typename" A::X x above should be: typename A::X x B::Y y above should be: typename B::Y y Resolution: Requestor: Owner: Bill Gibbons (Templates) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 15 - Exception Handling --------------------------------- Work Group: Core Issue Number: 769 Title: Are the base class dtors called if the derived dtor throws an exception? Section: 15.2[except.dtor] Status: active Description: [Mike Ball, core-7288:] #include struct base{ ~base() { cerr << "base\\n";} }; struct derived : public base{ ~derived() { throw("error"); } }; void doit() { derived x; } int main() { try { doit(); } catch(...) { } return 0; } Should the destructor for "base" be executed? The answer is not in the DWP, though it does state that it will be executed if the destructor for "derived" has a function catch block. I would consider this an obvious editorial matter were it not that I can think of reasons that the programmer might want the base class destructors not to be executed. For example, there is otherwise no way to abort a destructor in the middle. The current specification provides a way to achieve that. The programmer could have the base destructors executed by providing a function catch block and have them skipped by not providing one. This is pretty thin reasoning, but it implies that this is not so obvious. [Jerry Schwarz, core-7289:] I assume that the destructor for the base class wouldn't be called. To clarify my reasoning: the calling of the base subobject's destructor is part of the execution of the derived class constructor, and it wouldn't be executed any more than would statements following the throw. And I'll note that the same question might be asked about the member subobjects. For which I assume the answer would be the same. (Whatever that is.) [Bjarne, core-7290:] It has been a principle throughout that constructed sub-objects are destroyed if a constructor throws an exception. Consider a base an unnamed member and it all works out. [John Skaller, core-7294:] I assume the base destructor IS called. There are TWO reasons to destroy the object, the first is that the user code invoked the destructor, and the second is that the exception requires object/stack unwinding. Even if the exception is somehow caught, that still leaves the program to continue destroying the object normally. The only way the destruction can be stopped is by calling a special handler, terminate() or perhaps unexpected(). [Erwin Unruh, core-7297:] My opinion is that a compound statement can be seen as a corner case of a try statement which just has no handler. In this light I would argue to have the same semantics with a compound statement than with a handler whose catch clauses don't match. This would argue in calling the base destructors. This would not allow base destructors to be avoided. But if a programmer wants this, he can put a flag into the base object and have the destructor check this flag. So the restriction is not too hard. Current practice: [Anthony Scian, core-7299:] I tried the program under Watcom C++, MS VC++, and Borland C++ with the result that all three C++ implementations destructed the base class. Resolution: Requestor: Mike Ball Owner: Bill Gibbons (Exception Handling) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Chapter 16 - Preprocessing Directives --------------------------------------- ============================================================================= Annex C - Compatibility ------------------------- Work Group: Core Issue Number: 680 Title: Annex C subclause C.1 is out of date Section: C.1 [diff.c] Status: editorial Description: Jonathan Schilling wrote the following: The introduction to Annex C (Compatibility) and subclause C.1 (Extensions) both look like they were quickly edited from the base document for use in the standard, but the edit missed some spots and left others making no sense ("... from the dialects of Classic C used up till now", "... since the 1985 version of this manual"). More attention is given to Classic C than is now necessary, and the new features list is very incomplete. The proposed rewrite of the introduction and subclause C.1 is below. An alternative course of action would be to drop C.1 altogether, but I think that once made accurate it serves a useful purpose. Proposed Resolution: Replaced C.1 and C.1.1 with: Annex C (informative) Compatibility [diff] This Annex summarizes the evolution of C++ and explains in detail the differences between C++ and ISO C, both in the language and in the standard library. With the exceptions listed in this Annex, programs that are both C++ and C have the same meaning in both languages. All differences between C++ and C can be diagnosed by an implementation, although converting programs between C++ and C may be subject to the vicissitudes of unspecified and undefined behavior. C.1 Extensions [diff.c] This subclause summarizes the major extensions to C provided by C++. Because C++ was originally based upon the C of the first edition of _The C Programming Language_, before C became an ISO standard, there was some parallel evolution between the two languages. This is noted here by the phrase "also in ISO C". C.1.1 C++ features available in 1985 [diff.early] This subclause summarizes the extensions to C provided by C++ by 1985, as described in the first edition of _The C++ Programming Language_: < same feature list that's in current [diff.early] > C.1.2 C++ features added 1985 - 1991 [diff.mid] This subclause summarizes the major extensions to C++ between 1985 and 1991, as described in the second edition of _The C++ Programming Language_: < same feature list that's in current [diff.c++], except: take out "The bool type" (20) take out the references to things being "moved to the anachronism subclause" (5, 8) > C.1.3 C++ features added since 1991 [diff.late] This subclause summarizes the major extensions to C++ since 1991, as described in this International Standard: Universal character names ([lex.charset]), trigraphs ([lex.trigraph]), and operator keywords ([lex.key]). The bool type; [basic.fundamental]. The wchar_t type; [basic.fundamental]. User-defined new and delete operators for arrays; [expr.new], [expr.delete]. Placement delete; [expr.new]. Run-time type identification, including dynamic_cast and typeid; [expr.dynamic.cast], [expr.typeid]. A new form for casts: static_cast ([expr.static.cast]), reinterpret_cast ([expr.reinterpret.cast]), and const_cast ([expr.const.cast]). Declarations in tested conditions in if, switch, for, and while statements; [stmt.select], [stmt.iter]. Namespaces; [basic.namespace]. Class members can be declared mutable; [decl.stc]. The explicit keyword for providing non-converting constructors; [dcl.fct.spec]. Forward declaration of nested classes; [class.nest]. Static data member constants; [class.static.data]. Relaxation of the rule for return types of overriding functions; [class.virtual]. Overloading based on enumerations; [over.load]. Refinement of the template compilation model and addition of the export keyword; [temp]. The typename keyword in template parameters; [temp.param]. Default arguments for template type parameters; [temp.param]. Default arguments for template type parameters; [temp.param]. Explicit template argument specification in template function calls; [temp.arg.explicit]. Explicit template instantiation; [temp.explicit]. New syntax for template specialization; [temp.expl.spec]. Partial specialization of class templates; [temp.class.spec]. Member templates; [temp.mem]. Function try blocks; [except]. The uncaught_exception() function; [except.uncaught]. The C++ Standard library; [lib.library]. Resolution: Requestor: Jonathan Schilling Owner: Tom Plum (C compatibility) Emails: compat-352 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 743 Title: Some anachronisms are missing from annex C Section: C.3 [diff.anac] Status: editorial Description: Annex C (Compatibility), subclause C.3 (Anachronisms), seems very odd as it stands. It covers only the oldest and probably least-used anachronisms supported by compilers. Only some of them relate to use of C programs as C++. A more current list would include lots of other things, such as anachronisms due to Cfront 3.0 peculiarities, anachronisms due to differences between the ARM and the WP, and so on (see the anachronism list for any commercial compiler for how long these can get, e.g. EDG). Jonathan proposes to reduce subclause C.3 to a single paragraph providing for anachronism support in general, without any specific items. The proposed wording: C.3 Anachronisms [diff.anac] Extensions to the C++ language may be provided by an implementation to ease the use of C programs as C++ programs or to provide continuity from earlier C++ implementations. Note that use of such extensions is likely to have undesirable aspects. An implementation providing them should also provide a way for the user to ensure that they do not occur in a source file. A C++ implementation is not obliged to provide these features. Resolution: At the Hawaii meeting, the C compatibility WG decided that annex C.3 should either be removed or rewritten. Requestor: Jonathan Schilling Owner: Tom Plum (C compatibility) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= Annex E - Universal-character-names ------------------------------------ Work Group: Core Issue Number: 770 Title: The title of Annex E needs to be made shorter Section: Annex E[extendid] Status: editorial Description: The top of page E-2 (Annex E) has the section title overlapping the date. Andrew Koenig responded the following: > The reason is that (major) clause titles aren't checked for > overlap with the date. The easiest fix is therefore to > rename clause E to something shorter. Resolution: Requestor: Owner: Tom Plum (Annex E) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ============================================================================= +---------------+ | Closed Issues | +---------------+ The following issues were resolved at the Hawaii meeting. These issues o were addressed by motions adopted at the Hawaii meeting, or o were editorial issues corrected by editorial actions at the Hawaii meeting, or o were rejected because the Core WG decided to take no action. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.8 [intro.execution]: 605: The execution model wrt to sequence points and side-effects needs work 693: What can be done within a signal handler? 2.1 [lex.phases]: 695: A source file must not end in a new-line character - is a diagnostic required? 2.8 [lex.header]: 696: What happens if // appears between < and >? 697: Should special characters in include file names be implementation-defined? 2.13 [lex.ccon]: 698: Should wide-character literals be well-defined for a given locale? 699: What is the size of a non-wide string literal that contains UCNs? 3.2 [basic.def.odr]: 700: Is a diagnostic required if a function or object is not defined? 3.3.1 [basic.scope.pdecl]: 701: Is a class type first used in the parameter list of a function definition introduced in the function outermost block? 3.4.2 [basic.lookup.koenig]: 702: When do "member functions" hide functions from associated namespaces? 703: What are the associated namespaces of a template-id? 3.4.4 [basic.lookup.elab]: 666: Are class names used in an elaborated-type-specifier hidden by namespace names? 3.4.5 [basic.lookup.classref]: 704: e.B::a, must B be an unambiguous base class of e's class? 3.5 [basic.link]: 526: What is the linkage of names declared in unnamed namespaces? 705: What is the linkage of non-exported templates? 706: extern block scope declarations and lookup of previous "matching" declarations 3.6.3 [basic.start.term]: 663: Should the meaning of a coexisting C/C++ implementation be defined? 3.7.3 [basic.stc.dynamic]: 667: What does "predeclared" operator new mean? 707: Implications of the predeclared operator new(size_t) 3.7.3.1 [basic.stc.dynamic.allocation]: 708: What can a user-declared allocation do if it fails to allocate storage? 3.9 [basic.types]: 709: Can one use memcpy to copy the content of objects of non-POD type? 3.10 [basic.lval]: 710: A union with a char array should alias with other types 4.2 [conv.array]: 668: Should the conversion from string-literal to pointer to char be an "array-to-pointer" conversion which has exact match rank in function overload resolution? 5.2.4 [expr.pseudo]: 715: cv-qualifiers and pseudo destructor calls 5.2.7 [expr.dynamic.cast]: 549: Is a dynamic_cast from a private base allowed? 5.2.8 [expr.typeid]: 716: Can a class type be defined in a typeid expression? 5.2.10 [expr.reinterpret.cast]: 717: Can a static_cast cast an incomplete class type to its own type? 5.3.4 [expr.new]: 638: When is access/ambiguity on operator delete checked? 5.5 [expr.mptr.oper]: 644: Must the operand of .* and ->* have a complete class type? 5.9 [expr.rel]: 670: Is the comparison between void* and cv T* well-formed? 5.17 [expr.ass]: 691: is bool += 1 valid? 5.19 [expr.const]: 723: Should pointer to member casts be allowed in pointer to member constant expressions? 6.2 [stmt.expr]: 645b: When is the result of an expression statement converted to an rvalue? 6.4.2 [stmt.switch]: 724: Should the integral constant-expression be converted to the promoted type of the switch condition? 6.7 [stmt.dcl]: 635: local static variable initialization and recursive function calls 725: Can a local object be initialized before the first time control passes through its declaration? 6.8 [stmt.ambig]: 671: Does template instantiation happen during parser ambiguity resolution? 7.1.2 [dcl.fct.spec]: 726: inline functions must be declared inline in all translation units - is a diagnostic required? 7.3.1.2 [namespace.memdef]: 727: In which namespace are names in extern block declarations and function block declarations looked up? 7.3.3 [namespace.udecl]: 673: Does a using-declaration for an enum type declare aliases for the enumerator names as well? 7.3.4 [namespace.udir]: 612: name look up and unnamed namespaces 7.5 [dcl.link]: 728: How are extern "C" objects declared or defined? 10.2 [class.member.lookup]: 674: How do using-declarations affect class member lookup? 10.3 [class.virtual]: 675: How do using-declarations influence the selection of a final virtual function overrider? 11.4 [class.friend]: 731: Do functions first declared as friends still have external linkage? 12.3 [class.conv]: 732: Should "explicit" be allowed on type conversion operators? 12.6 [class.init]: 138: When are default ctor default args evaluated for array elements? 13.3.1.1.2 [over.call.object]: 662: Do cv-qualifiers on the class object influence the operator() called? 13.3.3.2 [over.ics.rank]: 684: The ranking for implicit conversion sequences for pointer types should take into account qualification conversions in 4.4 685: What is the ranking of a user-defined conversion that combines a pointer conversion with casting away cv-qualifiers? 14.1 [temp.param]: 735: Semantics for some forms of the template parameter missing? 14.6 [temp.res]: 738: Can a template parameter be declared as a friend? 14.7.1 [templ.inst]: 676: When is a template instantiated? 14.8.2 [temp.deduct]: 739: How does argument deduction works if operator T is a member template? 15.1 [except.throw]: 678: Can the exception object created by a throw expression have array 15.4 [except.spec]: 740: Can an exception specification appear in a reference declaration? 15.5.3 [except.uncaught]: 741: The definition of uncaught_exception does not take into account nested exceptions clause 16: 679: "Shall" is used incorrectly in clause 16 742: Should __STDC__ be in the list of predefined macros? Annex C: 681: The type of string literals is array of const char - this has implicitions for C compatibility and should be in Annex C ============================================================================= Chapter 1 - Introduction -------------------------- Work Group: Core Issue Number: 605 Title: The execution model wrt to sequence points and side-effects needs work Section: 1.8 [intro.execution] Status: closed Description: See UK issues 263, 264, 265, 266: 1.8 para 9: "What is a "needed side-effect"? This paragraph, along with footnote 3 appears to be a definition of the C standard "as-if" rule. This rule should be defined as such. [Proposed definition of "needed": if the output of the program depends on it.]" Bill Gibbons also notes: > [1.8/1] The "as-if" rule seems too important to leave as a > footnote. I suggest promoting it to normative text in 1.3 or > expanding 1.8/1. We should probably name this rule so it can > be more easily referenced. 1.8 para 10: "It is not true to say that values of objects at the previous sequence point may be relied on. If an object has a new value assigned to it and is not of type sig_atomic_t the bytes making up that object may be individually assigned values at any point prior to the next sequence point. So the value of any object that is modified between two sequ