Accredited Standards Committee X3 Doc No: X3J16/95-0050 WG21/N0650 Information Processing Systems Date: Jan 31, 1995 Operating under the procedures of Project: Programming Language C++ American National Standards Institute Ref Doc: Reply to: Josee Lajoie (josee@vnet.ibm.com) +========================+ | Core WG List of Issues | +========================+ +-------+ | Core1 | +-------+ Linkage / ODR ------------- 3.2[basic.def.odr]: 113: Can an inline functions refer to static global variables? 427: When is a diagnostic required when a member function used is not defined? 428: ODR for block scope extern declarations 7.1.1[dcl.stc]: 437: How do extern declarations link with previous declarations? 7.5[dcl.link]: 78: Linkage specification and calling protocol 420: Linkage of C++ entities declared within `extern "C"'. Memory Model ------------ 3.8[basic.types]: 192: Should a typedef be defined for the type with strictest alignment? 5.9[expr.rel]: 201: Can void* be used in relational operators? new / delete ------------ 5.3.4[expr.new]: 435: Can reference types be newed? 436: What is the type of a new expression allocating an array? 5.3.5[expr.delete]: 340: Which delete operator must be used to delete objects and arrays? 416: delete expressions and abstract/imcomplete types. 426: Deleting arrays if element type differs from type of delete expression Order of Initialization/Destruction ----------------------------------- 3.6.2[basic.start.init]: 429: Order of intialization of reference variables 3.6.3[basic.start.term]: 430: Order of destruction of local static variables Object Model ------------ 1.6[intro.object]: 421: What is an object? a sub-object? 3.7[basic.stc]: 93: Deleting the "current object" (this) in a member function 5[expr]: 417: Should pointer arithmetic be allowed for pointer-to-abstract? 9.2[class.mem]: 143: Should data members be allocated with increasing addresses? 10.1[class.mi]: 11: How do retrictions on member mapping apply with multiple inheritance? 442: Can a class have a direct base and an indirect of the same type? 10.3[class.virtual]: 447: When should a class without a final overrider be ill-formed? 11.1[class.access.spec]: 22: How must implementations respect access restrictions? 11.2[class.access.base]: 284: access to base class ctor/dtor/copy assignment 12[special]: 379: Invoking member functions which are "not inherited" Construction / Destruction -------------------------- 12.4[class.dtor]: 135: When is the virtual mechanism used with destructor calls? 293: Clarify the meaning of y.~Y 12.6[class.init]: 138: When are default ctor default args evaluated for array elements? 12.6.2[class.base.init]: 298: When and why is an expression-list optional in a mem-initializer? 359: Timing of Evaluations in Base and Member Initializations 406b: Can a ctor-initializer initialize twice the same member? Class Copy ---------- 12.8[class.copy]: 95: Volatility, copy constructors, and assignment operators 306: Does generated assignment require lvalue left-hand operand? 380: What conditions cause an operator= to be generated? 381: May operator= be declared as `virtual'? +-------+ | Core2 | +-------+ Name Look Up ------------ 5.1[expr.prim], 12.4[class.dtor]: 433: What is the syntax for explicit destructor calls? 9.3[class.scope0]: 13: Is a class name inserted as a name in its own class scope? 440: When does the class scope start when a member is defined outside the class definition? 10.1[class.mi]: 443: How does the C struct hack affect base-clauses? 444: Is a base class name inserted as a name in the derived class scope? 445: If a base class is a nested class, what is its name in a derived class? 446: Can explicit qualification be used for base class navigation? 12.1[class.ctor]: 14: Is the name of a constructor a type name or a function name? 12.5[class.free]: 408: Ambiguity seleting operator delete() from virtual destructor 450: How is operator new/delete looked up? Types / Classes / Unions ------------------------ 7[dcl.dcl]: 213: Should vacuous type declarations be prohibited? 7.1.5[dcl.type]: 116: Is "const class X { };" legal? 7.1.5.3[dcl.type.elab]: 252: Where can the definition of an incomplete class object appear? 9.2[class.mem]: 257: Which properties attributed to classes members do not apply to unions? 9.6[class.union]: 335: Can unions contain reference members? 266: Access specifiers in union member list 105: How can static members which are anon unions be initialized? 9.9[class.local]: 270: Must a member function in a local class be defined? 389: Can a local class be abstract? Declarators ----------- 8.3.2[dcl.ref]: 438: Can a reference declaration specify a storage class? 8.3.5[dcl.fct] 439: Are there any restrictions on the parameter before the ellipsis? 9.7[class.bit]: 47: enum bitfields - can they be declared with < bits than required? 267: What does "Nor are there any references to bitfields" mean? Lvalues ------- 3.9[basic.lval]: 431: Are void expressions ever lvalues? Type Conversions / Function Overload Resolution ----------------------------------------------- 4.7[conv.integral]: 432: Integral conversions for bitfields 5.2.4[expr.ref]: 425: Can conversion ambiguities arise from evaluating the lhs of . or -> for static members? 5.2.8[expr.static.cast]: 434: Can the inverse of any standard conv by performed with a static cast? 12.3.2[class.conv.fct]: 347: Limitations on declarations of user-defined type-conversions 13.2.1.1.1[over.call.func]: 451: Description of a call to a member function through a pointer to member is missing Access Specifications & Friends ------------------------------- 7.1.5.3[dcl.type]: 224: Default access for: struct X; class X {...}; 9.8[class.nest]: 4: How do member access control apply to member definitions in namespace scope? 68: How do access control apply to members of nested classes in the definition of the owning class? 27: What is the access of nested class types declared multiple times in the owning class definition? 441: Who owns the base-clause? The nested class or the enclosing class? 11.1[class.access.spec]: 26: Can a private type be used in a public typedef? 11.3[class.access.dcl]: 388: Access Declarations and qualified ids 409: Cant promote public member of private base to protected access 11.4[class.friend]: 448: Can '::' be used to declare global functions as friends? 11.5[class.protected]: 449: Should static and nonstatic members be treated more similarly wrt access checking? =============================================================================== Chapter 1 - Introduction -------------------------- Work Group: Core Issue Number: 421 Title: What is an object? a sub-object? Section: 1.6 [intro.object] Object Model Status: active Description: There appears to have been a recent substantive change in the definition of "sub-object" and "complete object" in the Working Paper. Sub-objects used to include only objects representing base classes. A complete object used to include all objects (even members) that aren't base class objects of other objects. Now sub-objects include members, and complete objects exclude members. This introduces a number of unfortunate side-effects in the standard where the definitions are used. For example: 5.4 A pointer to a complete class B may be explicitly converted to a pointer to a complete class D that has B as a direct or indirect base class if an unambiguous conversion from D to B exists (f4.6, f10.1.1) and if B is not a virtual base class (f10.1). Such a cast from a base to a derived class is only valid if the pointer points to an object of the base class that is actually a sub-object of an object of the derived class; the resulting pointer points to the enclosing object of the derived class. Otherwise (the object of the base class is not a sub-object of an object of the derived class) the result of the cast is undefined. This only makes sense with the old definitions. 12.6.2 ... The declaration order is used to ensure that sub-objects and members are destroyed in the reverse order of initialization. ... ... Any mem- initializers for virtual classes specified in a constructor for a class that is not the class of the complete object are ignored. Again, these only makes sense with the old definition. However, the following makes more sense with the new definition: 15.3 An object that is partially constructed will have destructors executed only for its fully constructed sub- objects.... because with the old definition, the following example constructs a C that is never destructed. extern "C" printf(const char *format, ...); struct C { C() { printf("Constructed a C.\n"); } ~C() { printf("Destructed a C.\n"); } }; struct D { D() { throw 3; } }; struct E { C c; D d; E() : c(), d() {} }; main() { try { E e; } catch(int x) { printf("caught %d\n", x); } } Resolution: Requestor: Neal M Gafter Owner: Josee Lajoie (Object Model) Emails: edit-195, edit-196 Papers: =============================================================================== Chapter 2 - Lexical Conventions --------------------------------- =============================================================================== Chapter 3 - Basic Concepts ---------------------------- Work Group: Core Issue Number: 113 Title: Can an inline functions refer to static global variables? Section: 3.2 [basic.def.odr] One Definition Rule Status: active Description: 7.1.2 p3 says: An inline member function must have exactly the same definition in every compilation unit in which it appears. Can an inline function accessed a file static variable? How can it do so and respect the statement describe above? Resolution: [JL:] An inline member function must have the same definition in different compilation units. Therefore it cannot access a file static variable. However, the ODR rule needs to be better defined and the Core WG is working on this. Requestor: Small issues / Core Language WG discussions Owner: Josee Lajoie (ODR) Emails: Papers: 94-0009/N0369 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 427 Title: When is a diagnostic required when a member function used is not defined? Section: 3.2 [basic.def.odr] One Definition Rule Status: active Description: p2.4 "If a non-virtual function is not defined, a diagnostic is required only if an attempt is actually made to call the function." Isn't it too severe to force an implementation to issue a diagnostic in the case? Shouldn't it be no-diagnostic required? Requestor: Josee Lajoie Owner: Josee Lajoie (ODR) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 428 Title: ODR for block scope extern declarations Section: 3.2 [basic.def.odr] One Definition Rule Status: active Description: Is a diagnostic required if 2 extern block scope declarations declare the same name with different attributes, i.e.: void f() { extern int a[5]; } void g() { extern int a[7]; } Requestor: Josee Lajoie Owner: Josee Lajoie (ODR) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 429 Title: Order of intialization of reference variables Section: 3.6.2 [basic.start.init] Initialization of non-local objects Status: active Description: Is the following initialization of "r" performed "statically" (that is, at link time) or "dynamicaly" (that is, at its turn among dynamically initialized nonlocal objects in the translation unit)? extern int x; int &r = x; Requestor: Neal Gafter Owner: Josee Lajoie (Construction/Destruction) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 430 Title: Order of destruction of local static variables Section: 3.6.3 [basic.start.term] Termination 6.7 [stmt.dcl] Declaration statement Status: open Description: 3.5.3 says static objects are destroy in reverse order of intialization. 6.7 says destruction order is unspecified. Which one is right? Requestor: Mike Ball Owner: Josee Lajoie (Construction/Destruction) Emails: core-4989 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 93 Title: Deleting the "current object" (this) in a member function Section: 3.7 [basic.stc] Object Lifetime Status: active Description: In a standard conforming program, may delete be used within a non-static member function (or within a function which is called directly or indirectly by such a function) to delete the object for which the non-static member function was called? Example: struct S { void member (); }; void delete_S (S *arg) { delete arg; } void S::member () { delete_S (this); } If this is prohibited in a standard conforming program is a standard conforming implementation required to issue a diagnostic for such code? Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Object Model) Emails: core-1650 Papers: 94-0185/N0572 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 192 Title: Should a typedef be defined for the type with strictest alignment? Section: 3.8 [basic.types] Types Status: active Description: It would be useful if provided a typedef for a name such as __strict_align_t , to describe a type whose alignment is the strictest required in this environment. It is otherwise hard to write a portable overloaded new operator. Faking it, by defining a union of several "typical" types, is not really portable, and its quiet mode of failure might be extremely puzzling, because the program would run just fine most of the time in most environments, except that in some unusual environment the program would occasionally produce an alignment error. As WG14 and X3J11 have found out, some compilers add an alignment requirement for structures embedded inside structures, one which is even more restrictive than the scalar types! There are no real-world guarantees about alignment, unless the committee imposes them. ALTERNATIVE: The committee could prescribe specific requirements for alignment. E.g., in any conforming environment, no object may have an alignment requirement more restrictive than this specific type: struct _strict_align_t { struct { long n; double d; }; }; 92/12/07 NOTE: To allow the writing of portable allocators, it may also be necessary to define an __align_pointer(p) function, which returns the nearest pointer (address) value which is aligned on the strictest boundary and is greater than or equal to the pointer value p . Resolution: Requestor: Tom Plum / Dan Saks Owner: Josee Lajoie (Memory Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 431 Title: Are void expressions ever lvalues? Section: 3.9 [basic.lval] Lvalues and rvalues Status: active Description: In ISO C, expressions having type void are never considered to be lvalues. Thus, the following code violates a constraint of the C standard, and conforming implementations are required to issue a diagnostic: void *vp; void foo () { &*vp; /* constraint violation */ } Are expression have THE void type and/or expressions having some qualified void type every considered to be lvalues in C++? Resolution: Requestor: Ron Guilmette Owner: Steve Adamczyk (Lvalues) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . =============================================================================== Chapter 4 - Standard Conversions ---------------------------------- Work Group: Core Issue Number: 432 Title: Integral conversions for bitfields Section: 4.7 [conv.integral] Integral conversions Status: active Description: p3 "If the destination type is signed, the value is unchanged if it can be represented in the destination type; otherwise, the value is implementation-defined." Is the width of a bitfield part of its type? struct S { signed int b : 2; } s; s.b = 100; //1 Here, is the destination type 'signed int' or 'signed int bitfield of size 3'? I don't believe the rule above covers the fact that the conversion on line //1 has undefined behavior. Requestor: Josee Lajoie Owner: Steve Adamczyk (Type Conversions) Emails: Papers: =============================================================================== Chapter 5 - Expressions ------------------------- Work Group: Core Issue Number: 433 Title: What is the syntax for explicit destructor calls? Section: 5.1 [expr.prim] Primary expressions 12.4 [class.dtor] Destructors Status: active Description: Question 1: p10 says: The notation for explicit call of a destructor may be used for any simple type name. For example: int* p; p->int::~int(); Must the destructor name be a qualified-id or can it be written as: p->~int(); ? Question 2: Can a typedef name can be used following the ~, and if so, what are the lookup rules? struct A { ~A(){} }; typedef class A B; int main() { A* ap; ap->A::~A(); // OK ap->B::~B(); // cfront/Borland OK, IBM/Microsoft/EDG error ap->A::~B(); // cfront OK, Borland/IBM/Microsoft/EDG error ap->~B(); // OK? } This issue concerns the lookup of explicit destructor calls for nonclass types as well. typedef int I; typedef int I2; int* i; i->int::~int(); i->I::~I(); i->int::~I(); i->I::~int(); i->I::~I2(); Which of these are well formed? Resolution: Requestor: John H. Spicer Owner: Steve Adamczyk (Name Look Up) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 417 Title: Should pointer arithmetic be allowed for pointer-to-abstract? Section: 5.2.1, 5.2.5, 5.3.1, 5.3.2, 5.7 Status: active Description: Should pointer arithmetic and/or the sizeof operator be allowed for operands whose type is some pointer-to-abstract type? Quite simply, I believe that the answer is NO because any kind of pointer arithmetic, when applied to an operand whose type is some pointer-to-abstract type, is quite likely to yield results which are, at best, misleading, incorrect, and useless. (Note that pointer arithmetic is already disallowed for any operand whose type is some pointer-to-incomplete type. A restriction prohibiting arithmetic on pointer-to-abstract type operands would simply mirror the current restrictions with respect to pointer-to-incomplete type operands.) In a similar vein, it could be effectively argued that taking the `sizeof' an abstract type (or of an expression having such at type) should be disallowed, just as it is for incomplete types. Note that if it is the committee's judgement to effect such restrictions, these restrictions would have to be reflected in working paper sections 5.2.1, 5.2.5, 5.3.1, 5.3.2, and 5.7. Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Object Model) Emails: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 425 Title: Can conversion ambiguities arise from evaluating the lhs of . or -> for static members? Section: 5.2.4 [expr.ref] Class member access Status: active Description: San Diego motion 29 states that the left-hand-side of a . or -> operator is always evaluated. That would imply that the following program exhibits an ambiguity error in the call to d.f(2) because D has no unique A subobject to access. Is this really supposed to be ill-formed? Am I making all this up? It should be made clear in the WP either way. struct A { static void f(int) {}; }; struct B : A {} struct D : A, B {} main() { D d; d.f(2); } Resolution: Requestor: Neal M Gafter Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 434 Title: Can the inverse of any standard conv by performed with a static cast? Section: 5.2.8 [expr.static.cast] Static Cast Status: open Description: p6 says: "The inverse of any implicit conversion can be performed with a static cast." I don't believe this is accurate. For example: int a[5]; 'a' can be converted from: 'array of 5 ints' to 'pointer to int'. int *p; can 'p' be converted to an array of 5 ints using a static_cast? Resolution: Requestor: Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 435 Title: Can reference types be newed? Section: 5.3.4 [expr.new] New Status: active Description: p2 says: "The new-type in a new-expression is the longest possible sequence of new-declarators. This prevents ambiguities between declarator operators &, *, [], and their expression counterparts." This indicates that: 'new int & i' will be parsed as: (new int&)i what does it mean to new a reference type? Resolution: Requestor: ? Owner: Josee Lajoie (New) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 436 Title: What is the type of a new expression allocating an array? Section: 5.3.4 [expr.new] New Status: active Description: Bill Gibbons says: The type of the expression 'new T' should be T* (always). The decay to pointer to first element should only occur when the explicit array bound is used in the new expression. This allows template argument to be used to allocate arrays. Resolution: Requestor: Bill Gibbons Owner: Josee Lajoie (New) Emails: core-3709 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 340 Title: Which delete operator must be used to delete objects and arrays? Section: 5.3.5 [expr.delete] Delete Status: active Description: Section 5.3.5 says: "In the ... alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object created by a new expression." This statement fail to take account of the fact that an "array object" may itself be considered to be an "individual object". Here is an example which illustrates this point: typedef int array_type[20]; void foobar () { array_type *p = (array_type *) new array_type; delete p; // undefined behavior??? } In this example, the current rules fail to make it completely clear whether or not the delete statement shown produces undefined behavior. Only one "object" is being deleted here, but that object happens to have an array type (a fact which the implementation could easily deduce from the static type of the pointer expression `p' given in the delete statement). [Note JL:] This is also a problem when delete is used in template definitions. template void f(T* pt) { delete pt; // What form of delete should be used here? } If T happens to be an array type, than the form of delete selected here is not appropriate. Bill Gibbons suggested the following solution: The form of delete should match the syntactic form of the new (array or non-array), not the type used in the new expression. This allows template type arguments to be used to allocate arrays. Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Delete) Emails: core-3709 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 416 Title: delete expressions and abstract/imcomplete types. Section: 5.3.5 [expr.delete] Delete Status: active Description: Ron would like to see the following rules apply to the cast-expression of a delete expression: The type of the cast-expression given in a delete expression must be a pointer type. Further, the type which would result from applying the built-in unary `*' operator to this cast-expression (i.e. the referent type) must be a complete non-abstract object type, with the following exceptions: (a) The referent type of the cast-expression may be an incomplete class type. (b) The referent type of the cast-expression may be an abstract class type, provided that this type was earlier defined to contain a virtual destructor. If the type of the cast-expression given in a delete expression is not a pointer type, or if its referent type does not meet the requirements stated above, then the translation unit containing the delete expression is ill-formed." Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Delete) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 426 Title: Deleting arrays if element type differs from type of delete expression Section: 5.3.5 [expr.delete] Delete Status: active Description: Current WP disallows deleting an array using a pointer with a static type different from the type used in allocation. That is it prohibits class B { virtual ~B() ; } ; class D : public B { } ; B* pb = new D[10] ; delete[] pb ; This used to make some sense because the overheads of figuring out exactly what to do might be significant. (E.g. in the presence of MI pb might not even point to the start of the array.) But now that we have RTTI, there has to be enough information (in the vtbl) to determine the beginning of the array and its type. So I believe that this prohibition could reasonably be lifted. Resolution: Requestor: Jerry Schwarz Owner: Josee Lajoie (Delete) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 201 Title: Can void* be used in relational operators? Section: 5.9 [expr.rel] Relational Operators Status: active Description: 5.9p2 (Relational) allows: char *pc; void *pv; if ( pc < pv ) // ... i.e., ptr-to-object can be compared less-than (or greater-than) with a void* pointer. We have no serious objection; it's just looser than C allows. It's a "C difference", but not a "C incompatibility". It's philosophically a bit strange, though, that C++ aims to be more type-safe than C, but allows such free-and-easy use of a "typeless type" like void* . Should it be prohibited to compare a void* to a pointer to another type? Resolution: Requestor: Tom Plum / Dan Saks Owner: Josee Lajoie (Memory Model) Emails: Papers: 94-0118R1/N0505 section 1.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . =============================================================================== Chapter 6 - Statements ------------------------ Work Group: Core Issue Number: 132 (WMM.83) Title: Consistency between "::" and "Class::" in declarations Section: 6.8 [stmt.ambig] Ambiguity resolution Status: active Description: WMM.83. Is a change necessary for syntactic consistency between the treatment of "::" and "class::" in declarations? float a; float b; main(){ int (a) ; // valid block scope redeclaration of a int (::b); // valid function like cast of b } Note that the reason for the "function like cast" interpretation is that "::b" can *only* be used as a reference, and never used as a declarator. struct T { static a;}; int (T::a); // valid declaration and definition of T::a main(){ int (T::a); // semantic error: attempt to redeclare T::a (int)(T::a); // cast of T::a } Since the syntax allows "T::a" to be used as a declarator, the statement: int (T::a); is interpreted as a declaration even though this declaration is not valid at block scope. And eventhough the statement: int (T::a); is an invalid block scope declaration, it is not interpreted as an expression because it is validated as a declaration by the grammar. Should the syntax "Class::" always be interpreted as a reference instead of a part of a declaration when placed inside block scope? Resolution: Requestor: Mike Miller / Jim Roskin Owner: Syntax WG Emails: core-629 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 424 Title: Must disambiguation update symbol tables? Section: 6.8 [stmt.ambig] Ambiguity resolution Status: active Description: The question is about the following sentence from 6.8p4 [stmt.ambig] WP> The disambiguation is purely syntactic; that is, the meaning of the WP> names, beyond whether they are type-ids or not, is not used in the WP> disambiguation. One the one hand, this would imply that a trial parser needn't update a symbol table, since that would be processing that is not purely syntactic. On the other hand, some input would be disambiguated differently if the symbol table were updated during trial parsing. Symbol table updates would determine which names will be type-ids during the actual parse. To be more concrete and specific about the problem, consider the statement in main() in the enclosed test case. Should this be disambiguated as a declaration with a syntax error, or should it be disambiguated as a well-formed expression? struct T1 { T1 operator()(int x) { return T1(x); }; int operator=(int x) { return x; }; T1(int) {}; }; struct T2 { T2(int) {}; }; int a, (*(*b)(T2))(int), c, d; void main () { // Is the following a declaration with a syntax error? // Or is it a semantically valid expression? T1(a) = 3, T2(4), (*(*b)(T2(c)))(int(d)); } Resolution: Requestor: Neal M Gafter Owner: Syntax WG Emails: Papers: =============================================================================== Chapter 7 - Declarations -------------------------- Work Group: Core Issue Number: 213 Title: Should vacuous type declarations be prohibited? Section: 7 [dcl.dcl] Declarations Status: active Description: 7p19b: Should the draft prohibit vacuous decls like this? enum { }; class { int i; }; class { }; typedef enum {}; Resolution: Requestor: Tom Plum / Dan Saks Owner: Steve Adamczyk (Types) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 437 Title: How do extern declarations link with previous declarations? Section: 7.1.1 [dcl.stc] Storage class specifiers Status: active Description: What is the behavior of the following program: static int x; { int x; { extern int x; } } Is the block scope declaration of x "linked" to the global static declaration? If not, does this program break the ODR? Resolution: Requestor: Mike Holly Owner: Josee Lajoie (Linkage) Emails: core-5056 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 116 (WMM.65) Title: Is "const class X { };" legal? Section: 7.1.5 [dcl.type] Type Specifiers Status: active Description: Is "const class X { };" legal, and, if so, what does it mean? Resolution: Requestor: Mike Miller Owner: Steve Adamczyk (Classes) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 224 Title: Default access for: struct X; class X {...}; Section: 7.1.5.3 [dcl.type.elab] Elaborated Type Specifiers 11 Member access control Status: active Description: 7.1.5.3 a name declared as a class must be defined as a class or struct. What is the default access control for such a class? E.g., struct X; class X { ... }; Default access is private or public? Resolution: Requestor: Tom Plum / Dan Saks Owner: Steve Adamczyk (Access Specifications) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 252 Title: Where can the definition of an incomplete class object appear? Section: 7.1.5.3 [dcl.type.elab] Elaborated type specifiers Status: active Description: must IOT be completed in the same scope? 9.1p24 LA523 In C, a struct-or-union of incomplete type must be completed in the same scope as the incomplete-type declaration, or it remains an incomplete type. [We believe the same is intended for incompletely-defined classes in C++, but the document is not yet clear enough to tell.] [ Note JL: ] What about the following test case: class C; //1 union { class C { ... }; //2 ... }; Does line //2 defines the class declared on line //1? Resolution: Requestor: Tom Plum / Dan Saks Owner: Steve Adamczyk (Types) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 78 (also WMM.38) Title: Linkage specification and calling protocol Section: 7.5 [dcl.link] Linkage Specifications Status: active Description: extern "C" { // Typedef defined in extern "C" blocks: // What is the linkage of the function pointed at by 'fp'? typedef int (*fp)(int); // Type of a function parameter: // What is the linkage of the function pointed at by 'fp2'? int f(int (*fp2) (int)); // Can function with C linkage be defined in extern "C" blocks? int f2(int i) { return i; } // Can static function with C linkage be defined in // extern "C" blocks? static int f3(int i) { return i; } } If function declarations/definitions placed inside the extern "C" block have different properties from the ones placed outside these blocks, many areas of the C++ language will have to be aware of difference. i.e. a. function overloading resolution b. casting one will need to be able to cast from a pointer to a function with linkage "X" to a pointer to a function with linkage "Y". In short, it needs to be determined to what extent the linkage is part of the type system. [ JL: ] The standard should not force implementations to accept the following code: extern "SomeLinkage" int (*ptr)(); int (*ptr_CXX)(); ptr_CXX = ptr; // 1 i.e. an implementation should be able to issue an error for line (// 1). Resolution: Requestor: John Armstrong (johna@kurz-ai.com) Owner: Josee Lajoie (Linkage) Emails: core-1583, core-1584, core-1585, core-1586, core-1587, core-1589 core-1590, core-1591, core-1594, core-1595, core-1597, core-1598 core-1599, core-1608, core-1609, core-1612 core-920 (Hansen),core-985 (O'Riordan),core-1064 (Miller) Papers: 94-0034/N0421 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 420 Title: Linkage of C++ entities declared within `extern "C"'. Section: 7.5 [dcl.link] Linkage Specification Status: active Description: Given a declaration or definition of some C++ entity (e.g. a data member, a function member, and overloaded operator, an anonymous union object, etc) whose existance within an otherwise standard conforming program written in ANSI/ISO C would be a violation of the language rules, what is the effect of the linkage specification on the declarations/definitions of the C++ specific entities: Example: extern "C" { struct S { int data_member; }; int operator+ (S&, int); } Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Linkage) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . =============================================================================== Chapter 8 - Declarators ------------------------- Work Group: Core Issue Number: 438 Title: Can a reference declaration specify a storage class? Section: 8.3.2 [dcl.ref] References Status: active Description: And if it can, what does it mean? Resolution: Requestor: Owner: Steve Adamczyk (Declarators) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 439 Title: Are there any restrictions on the parameter before the ellipsis? Section: 8.3.5 [dcl.fct] Functions Description: Can the parameter before the ellipsis be a reference? A class with constructor? Resolution: Requestor: Owner: Steve Adamczyk (Declarators) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . =============================================================================== Chapter 9 - Classes --------------------- Work Group: Core Issue Number: 143 Title: Should data members be allocated with increasing addresses? Section: 9.2 [class.mem] Class Members Status: active Description: 9.2/9 says: "Nonstatic data members of a class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object." Why is this? It seems to unnecessarily restrict implementations from producing the most efficient layout. Is this restriction really necessary for non-POD class types? Resolution: Requestor: Sam Kendall Owner: Josee Lajoie (Object Model) Emails: core-1670 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 257 Title: Which properties attributed to classes members do not apply to unions? Section: 9.2 [class.mem] Class Members Status: active Description: 9.2p91: The "higher addresses" property should say "(non-union)" classes. Obviously. But do any of the other properties of classes exclude unions? ... Resolution: Requestor: Tom Plum / Dan Saks Owner: Steve Adamczyk (Unions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 13 Title: Is a class name inserted as a name in its own class scope? Section: 9.3 [class.scope0] Scope Rules for classes Status: active Description: struct A { typedef int B; }; struct B : A { B(); B(const B&); B *b; void f(const B); }; For all these cases, which name 'B' is selected? Is the name struct B visible in its own class scope? If the name was inserted, how would it interact with other type/identifier names and, in particular, the name of its constructor? Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Name Look Up) Emails: core-1461 Papers: 94-0057/N0444 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 440 Title: When does the class scope start when a member is defined outside the class definition? Section: 9.3 [class.scope0] Scope Rules for classes Status: active Description: struct T { enum E { e = 3 }; static int x[e]; }; int T::x[e] = { 1, 2, 3 }; Is the "e" in "int T::x[e]" found in class scope or not? Suggested resolution: No. When the definition of a class member is written outside the class, the identifiers in the member's declarator are not searched for in class scope. Rationale: The name lookup rules within a class specify two kinds of name lookup: that for identifiers in "declaration scopes", and that for identifiers in "expression scopes". Expression scope applies to identifiers written within function bodies, base/member initializers and default arguments. Declaration scope applies to all other identifiers within the class. Identifiers in declaration scope are looked up immediately; those in expression scope are looked up at the end of the class. Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Name Look Up) Emails: core-4108 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 335 Title: Can unions contain reference members? Section: 9.6 [class.union] Unions Status: active Description: union { int *p; int &r; }; int i, i; p = &i; r = 1000; Resolution: Requestor: John Armstrong Owner: Steve Adamczyk (Unions) Emails: core-2028 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 266 Title: Access specifiers in union member list Section: 9.6 [class.union] Unions Status: active Description: 9.6p3.2 - anonymous union may not have private or protected members. This seems to imply that anonymous union may have public members; and that non-anonymous union may have any access modifiers. Is this wording really what is intended? Resolution: Requestor: Tom Plum / Dan Saks Owner: Steve Adamczyk (Unions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 105 (WMM.27) Title: How can static members which are anon unions be initialized? Section: 9.6 [class.union] Unions Status: active Description: This is from Mike Miller's list of issues: class C { static union { int i; char * s; }; static int j; }; int A::j = 3; int A::i = 3; // ? Is this syntax valid? Resolution: Requestor: Mike Miller Owner: Steve Adamczyk (Unions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 47 Title: enum bitfields - can they be declared with < bits than required Section: 9.7 [class.bit] Bitfields Status: active Description: enum ee { one, two, three, four }; struct S { ee bit:1; // allowed? }; Resolution: Requestor: ? Owner: Steve Adamczyk (Declarators) Emails: core-1578 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 267 Title: What does "Nor are there any references to bitfields" mean? Section: 9.7 [class.bit] Bitfields Status: active Description: 9.7p3.5: "Nor are there references to bit-fields." Does this actually prohibit anything? A simple attempt to make a reference refer to a bit-field just creates a temporary: union { int bitf:2; } u; const int & r = u.bitf; Or is this a syntactic restriction that prohibits something like union { int (&rbitf):2 } u; Or is it meant to prohibit the use of typedefs to attempt it, such as union { typedef int bitf_t:2; bitf_t &rbitf; } u; The intent needs clarifying. 92/12/17: I think this point is directly at issue in Sam Kendall's proposal to unify the concept of lvalue and reference: an lvalue expression can designate a bitfield object, but the type of that object cannot be adjusted to a reference type. (or something like that) Resolution: Requestor: Tom Plum / Dan Saks Owner: Steve Adamczyk (Declarators) Emails: Papers: 92-0053 Merging Lvalue and Reference - Sam Kendall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 4 Title: How do member access control apply to member definitions in namespace scope? Section: 9.8 [class.nest] Nested Class Declarations Status: active Description: class enclose { class inner { void f(int i); static int j; }; }; void enclose::inner::f(int i) { ... } Where can a private nested type name be used? Should the language clarify that private types can be referred to as 'inner' is here following the '::' to define class member functions at global scope? This even though the use of 'enclose::inner' is not permitted outside of the scope of class enclose? enclose::inner c; // ill-formed, // private type enclose::inner cannot be used Resolution: Requestor: Ron Guilmette Owner: Steve Adamczyk (Access Specifications) Emails: core-1426, core-1427, core-1428, core-1430, core-1514 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 68 (WMM.58) Title: How do access control apply to members of nested classes in the definition of the owning class? Section: 9.8 [class.nest] Nested Class Declarations Status: active Description: From Mike Miller's list of issues: How is access control applied to members of nested classes? class X { class Y { enum E { E1, E2 }; }; public: Y::E f() { return Y::E1; } //1 }; Can Y::E be accessed as shown on line //1? Can Y::E1 be accessed as shown on line //1? The WP does not specify this. Resolution: Requestor: Mike Miller Owner: Steve Adamczyk (Access Specifications) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 27 Title: What is the access of nested class types declared multiple times in the owning class definition? Section: 9.8 [class.nest] Nested Class Declarations Status: active Description: struct ss { public: struct s; union u; class c; protected: struct s; union u; class c; private: struct s; union u; class c; }; What is the accessibility of s, u, c? Resolution: Requestor: Ron Guilmette Owner: Steve Adamczyk (Access Specifications) Emails: core-1517 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 441 Title: Who owns the base-clause? The nested class or the enclosing class? Section: 9.8 [class.nest] Nested Class Declarations Status: active Description: class C { class A { }; class B : A { }; //1 }; Is the declaration on line //1 invalid because the nested class B cannot refer to the private types declared in C? Resolution: Requestor: Owner: Steve Adamczyk (Access Specifications) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 270 Title: Must a member function in a local class be defined? Section: 9.9 [class.local] Local Class Declarations Status: active Description: 9.9p2.2: Says "Member functions of a local class must be defined within their class definition." Does this literally mean "MUST be defined", or does it mean "may not be defined anywhere but within ..."? Resolution: Requestor: Tom Plum / Dan Saks Owner: Steve Adamczyk (Classes) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 389 Title: Can a local class be abstract? Section: 9.9 [class.local] Local Class Declarations Status: active Description: 9.9 asserts that "member functions of a local class must be defined within their class definitions". Since declaring a virtual function as pure does not constitute defining it (see 10.3), 9.9 has the effect of prohibiting pure virtual functions from local classes and therefore of prohibiting abstract local classes. On the other hand, pure virtual functions are explicitly exempted from the general requirement that a virtual function must be defined somewhere (10.2). If a pure virtual function in a nonlocal class doesn't have to be defined, why not treat virtual functions of local classes the same? Resolution: Mike Anderson's proposed resolution: A consistent specification of local classes would require changing the sentence from 9.9 cited above to read: Member functions of a local class must be defined within their class definition or declared pure. (If no such change is made, 9.9 and/or 10.3 should be changed to explicitly prohibit abstract local classes.) Requestor: Mike Anderson Owner: Steve Adamczyk (Classes) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . =============================================================================== Chapter 10 - Derived classes ------------------------------ Work Group: Core Issue Number: 11 Title: How do retrictions on member mapping apply with multiple inheritance? Sections: 10.1 [class.mi] Multiple Base Classes Status: active Description: 10.1 paragraph 2 says that the order of derivation may be significant to the storage layout. How do the restrictions described in 9.2 paragraph 7 relate to members declared in base classes? Resolution: Requestor: Scott Turner Owner: Josee Lajoie (Object Model) Emails: core-1456 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 442 Title: Can a class have a direct base and an indirect of the same type? Sections: 10.1 [class.mi] Multiple base classes Status: active Description: class A { }; class B : public A { }; class C : public A, public B { }; Is this allowed? Since class A's members can never be referred to, can an implementation optimize the mapping for class C and not map the direct base class A? CFRONT omitted mapping the direct base class A. Resolution: Requestor: Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 443 Title: How does the C struct hack affect base-clauses? Section: 10.1 [class.mi] Multiple Base Classes Status: active Description: If a class/struct name is declared in a scope where an object, function, or enumerator of the same name is also declared, can that class/struct be used as a base class? class X { }; int X; class Y : X { }; Because the elaborated-type-specifier syntax 'struct X' cannot be used in a base-clause, the programmer cannot indicate that it wants name look up to find the class type X using the elaborated-type-specifier syntax. However, the compiler could use the context to determine that name look up should search for a type (only). Should this be the case? Resolution: Requestor: Owner: Steve Adamczyk (Name Look Up) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 444 Title: Is a base class name inserted as a name in the derived class scope? Section: 10.1 [class.mi] Multiple base classes Status: active Description: struct A { int i; }; struct B : A { int A; void f() { A::i; }; //1 B(); }; On line //1, which name 'A' is selected? Is the name of the base class A visible in its derived class scope? If the name is inserted, how would it interact with other type/identifier (i.e. the names of the members of the derived class)? For example: B::B() : A(), A(2) { } // What is the error? -------- What if the name used to designate the base class in the base-clause differs from the name by which the (base) class was originally declared? struct A { }; typedef A AA; struct B : AA { B(); }; // Which name is injected? B::B() : AA() { } // Is AA found on account of the automatic nesting // of the base class name in B? -------- If the base class is a template class, which name is injected? template struct T { T(int); }; struct B { typedef int T; struct S : ::T { S() : T(2) {} // Valid if template name T injected }; }; Resolution: Requestor: Scott Turner Owner: Steve Adamczyk (Name Look Up) Emails: core-1461 Papers: 94-0057/N0444 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 445 Title: If a base class is a nested class, what is its name in a derived class? Sections: 10.1 [class.mi] Multiple base classes Status: active Description: If a nested class X::nested is a base class for class A, must the base class be qualified in the scope class A: struct X { struct nested { }; }; struct A : X::nested { nested *pn; //1 error? }; Can 'nested' be referred to in the scope of the derived class A without qualification or must the name be qualified by its owning class? Resolution: Requestor: Owner: Steve Adamczyk (Name Look Up) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 446 Title: Can explicit qualification be used for base class navigation? Sections: 10.1 [class.mi] Multiple base classes Status: active Description: Can explicit qualification be used for base class sublattice navigation? class A { public: int i; }; class B : public A { }; class C : public B { }; class D { public: int i; }; class E : public D { }; class F : public E { }; class Z : public C, public F { }; Z z; ... z.F::E::D::i; // is qualification allowed here to navigate the base // class sublattice? Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Name Look Up) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 447 Title: When should a class without a final overrider be ill-formed? Sections: 10.3 [class.virtual] Virtual Functions Status: active Description: p7 shows: struct A { virtual void f(); }; struct B : virtual A { void f(); }; struct C : virtual A { void f(); }; struct E : B, C { }; //1 Is the declaration of E on line //1 ill-formed? Why not wait until an object of class E is created to issue the error message? Making the declaration of E on line //1 ill-formed prevents programs to further derive from E and override the virtual member function. i.e. struct F : E { void f(); }; Resolution: Requestor: Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . =============================================================================== Chapter 11 - Member Access Control ------------------------------------ Work Group: Core Issue Number: 22 Title: How must implementations respect access restrictions? Section: 11.1 [class.access.spec] Access Specifiers Status: active Description: What are the access restrictions used for? Are they only limitations on what the programmer may write? Must implementations also respect them for the compiler generated code? (i.e. use of default and copy constructors, use of destructors at the end of a block or at the end of the program). And if implementations must respect access restriction, when must it report the errors? struct B { private: ~B () { } }; struct D : public B { ~D () { } // is the mere existence of D::~D considered an // implicit call of B::~B and therefore a protection // violation? }; void f() { D d; // Or is this an error? } // Or is the error when d is destroyed? Resolution: Requestor: Jerry Schwarz Owner: Josee Lajoie (Object Model) Emails: core-1525 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 26 (also WMM.84) Title: Can a private type be used in a public typedef? Section: 11.1 [class.access.spec] Nested Class Declarations Status: active Description: class C { private: class D { /* ... */ }; typedef D DD; typedef int I; public: typedef D E1; typedef DD E2; typedef I II; }; C::E1 something1; // legal? D is private. C::E2 something2; // legal? DD is private. C::II something3; // legal? I is private. Resolution: Requestor: Mark Terrible Owner: Steve Adamczyk (Access Specifications) Emails: core-630, core-1513, core-1517 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 284 Title: access to base class ctor/dtor/copy assignment Sections: 11.2 [class.access.base] Access Specifiers for Base Classes Status: active Description: base access rules don't apply to non-inherited members 11.2 After much discussion, we believe that the intent is as follows: "The members whose accessibility is described in this section are only those members which are inherited from the base class; the non-inherited members such as constructors, destructors, and assignment operators are not subject to these accessibility rules." I still have problems with this one. There are two separate issues, one minor and one substantive. Minor issue: The ctor, dtor, and assignment op of a base are not accessible as "members of the derived class" (because they aren't inherited in the derived class), but I believe that access restrictions still apply to them. So it's just a job of re-wording 11.2/p1 to clarify this. But the substantive issue is a real problem. The vagueness has been unresolved so long that implementations have differed in the treatment of access declarations upon base class ctors and dtors. Could you discuss this with me and we'll determine how to proceed. Resolution: Requestor: Tom Plum / Dan Saks Owner: Josee Lajoie (Object Model) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 388 Title: Access Declarations and qualified ids Section: 11.3 [class.access.dcl] Access Declarations Status: active Description: The section says: The base class member is given, in the derived class, the access in effect in the derived class declaration at the point of the access declaration. It isn't clear to me what this means for class B { public: int i ; } ; class D : private B { B::i ; }; D* p ; p->i ; // clearly legal p->B::i ; I don't care strongly about this, but I think it should be clarified. (And added as an example). Resolution: Requestor: Jerry Schwarz Owner: Steve Adamczyk (Access Specifications) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 409 Title: Cant promote public member of private base to protected access Section: 11.3 [class.access.dcl] Access Declarations Status: active Description: From John Barton, comp.std.c++: What is the rationale for making this illegal? I think a derived class should be able to grant as much access as it has to any name in a private or protected base class. It makes no sense that a public name of a private base can be left private or made public in a derived class, but it cannot be make protected. class B { public: void pubB(); void pubB2(); protected: void protB(); }; class D : private B { public: B::pubB2; // OK. protected: B::protB; // OK B::pubB; // Error why?? Was private in D now protected. // D has access: pubB was public. }; Comment: possibly this is an oversight? Resolution: [ Note JL: ] Bjarne commented that this should be fixed with the 'using declarations' and that we shouldn't enhanced deprecated features. Requestor: John Max Skaller / John J. Barton (jjb@watson.ibm.com) Owner: Steve Adamczyk (Access Specifications) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 448 Title: Can '::' be used to declare global functions as friends? Section: 11.4 [class.friend] Friends Status: active Description: Should it be allowed to prefix the declarator of a friend function declaration with '::' to indicate that a global function is the friend? void f(); class C { void f(); friend void ::f(); }; or class B { void f(); }; class C { class B { }; friend void ::B::f(); }; Resolution: Requestor: Owner: Steve Adamczyk (Friends) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 449 Title: Should static and nonstatic members be treated more similarly wrt access checking? Section: 11.5 [class.protected] Protected member access Status: active Description: P1 of 11.5 now implies that: class C { protected: int i; static int j; }; class D : public C { void f(); }; void D::f() { C::i = 4; //OK, implied 'this' pointer, qualification ignored C::j = 6; //error, nested-name-specifier must represent the // derived class } The rules for static and nonstatic members should be as uniform as possible. In particular, changing a member from static to non-static or vice-versa should have no effect on the whether the program violates any access rules. But this isn't so in the proposed set of rules. Since we don't want to break the "implicit this" rules, I think the only solution is to allow friends and members of the derived class to access static members of the base class with a base class qualifier. That is, apply the access rules as if the member were nonstatic. This change would make the second line in the above example well-form Resolution: Requestor: Bill Gibbons Owner: Steve Adamczyk (Access Specifications) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . =============================================================================== Chapter 12 - Special Member functions --------------------------------------- Work Group: Core Language Issue Number: 379 Title: Invoking member functions which are "not inherited". Section: 12.1 [class.ctor] Constructors 12.4 [class.dtor] Destructors 12.8 [class.copy] Class Copy Status: active Description: Section 5.1/8 of the 1/93 working paper says: "A nested-class-specifier (9.1) followed by :: and the name of a member of that class (9.2) or a member of a base of that class (10) is a qualified-id; its type is the type of the member. The result is the member." Section 12.4/2 says: "Destructors are not inherited." Section 13.4.3/1 says: "The assignment function operator=() ... is not inherited." May a member of a given base class type which is "not inherited" by another class type (derived from the given base class type) be invoked for an object whose static type is the derived class type if the invocation is done using the class-qualified name syntax? If, not, is an implementation obliged to issue a compile-time diagnostic for such usage? Is the behavior "well defined" if an attempt is made to invoke a non-inherited member for an object whose static type is that of the base class but whose dynamic type is that of the derived class? struct B { virtual int operator= (int) { return 1; } ~B () { } }; struct D : public B { virtual int operator= (int) { return 0; } ~D () { } }; D D_object; D D_object2; B *B_ptr = &D_object2; void caller () { D_object.B::operator= (99); // ok? B_ptr->operator= (99); // ok? D_object.B::~B(); // ok? B_ptr->~B(); // ok? } Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Object model) Emails: Papers: 94-0193R1/N0580 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 14 (also WMM.66) / 290 Title: Is the name of a constructor a type name or a function name? Section: 12.1 [class.ctor] Constructors Status: active Description: If it is a function name, does it hide the type name? Also from Tom Plum and Dan Saks: define "constructor" and its "name" 12.1p11 says "A member function with the same name as its class is called a constructor...." But it's been mentioned that this is incorrect. Is a constructor a member function? What is its name? Other issues related to this topic: The reconsideration rule breaks copy constructors: struct S { S(S&); }; With the reconsideration rule, the name for the parameter type changes meaning when reconsidered in the completed scope of class S. Declarations like: struct S { S(); S* p; // error }; are made ill-formed by the reconsideration rule. Comments from Bjarne: A constructor is not a function name. It is a type name that can be used with the function call syntax. It cannot have its address taken. Resolution: Requestor: Tom Pennello Owner: Steve Adamczyk (Name Look Up) Emails: core-1463 Papers: 94-0057/N0444 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 347 Title: Limitations on declarations of user-defined type-conversions. Section: 12.3.2 [class.conv.fct] Conversion functions Status: active Description: Given a declaration such as: struct S { operator T (); }; ... where `T' is a typedef name declared in an earlier typedef declaration, must a standard conforming implementation issue a diagnostic for the declaration of the type conversion operator (as shown above) if, at the point of declaration of the type conversion operator itself, the type T is: o A complete array type? o An incomplete array type? o An incomplete class type? o A function type? Resolution: Requestor: Ron Guilmette Owner: Steve Adamczyk (Type Conversions) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 135 (WMM.86) Title: When is the virtual mechanism used with destructor calls? Section: 12.4 [class.dtor] Destructors Status: active Description: 12.4p8.1 says: Destructors are invoked ... explicitly using the destructor's fully qualified name. For virtual member functions, a qualifier suppresses the use of the object's run-time type to override the named function, i.e. it behaves non-virtually. If explicit destructor calls are virtual, regardless of the qualifier, this exception should be stated somewhere in 12.4. If explicit destructor calls are virtual when the qualifier is absent, and non-virtual when the qualifier is present, the requirement in 2.4p8.1 stating that the destructor name must be qualified should be removed. Resolution: Requestor: Mike Miller / Scott Turner Owner: Josee Lajoie (Destruction) Emails: core-641 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 293 Title: Clarify the meaning of y.~Y Section: 12.4 [class.dtor] Destructors Status: active Description: Resolution: 12.4p22 The notation y.~Y() is explicitly approved of by the example at bottom of ARM page 279), but nothing in the draft gives this explicit approval. Implementations differ. Committee should approve it or disapprove it. Requestor: Tom Plum / Dan Saks Owner: Josee Lajoie (Destruction) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 408 Title: Ambiguity seleting operator delete() from virtual destructor Section: 12.5 [class.free] Free Store Status: active Description: According to the WP, if a virtual destructor is used, it determines which operator delete() is called, however, the visible operator delete() is statically checked for access. It is not clearly specified, as it was in the ARM, that the operator delete() selected by a virtual destructor is the one which would have been visible from the most derived class; that is, the normal lookup rules are used. It is not clearly specified that when no virtual destructor is invoked by a delete expression that the expression is ill-formed if operator delete() is ambiguous. Example: struct L { void operator delete(void*); }; struct R { void operator delete(void*); }; struct D : L, R {}; delete new D; Recommendation: Its Ill-formed. Editor to incorporate example in WP. It is not specified what the behaviour is if a virtual destructor finds that operator delete is ambiguous. (Nor is it mentioned if there are any access restrictions) Example: struct L { virtual ~L(); void operator delete(void*); }; struct R { void operator delete(void*); }; struct D : L, R {}; delete (L*) new D; Discussion: If, in effect, operator delete is to be considered virtual, the object should not be permitted to be constructed. See also N0322, where I discuss the problem of overspecified virtual functions. On the other hand, if construction is permitted, the only possible action if a delete is attempted via a base class, is to throw an exception after the object is destroyed. Note that this issue is bound to arise if a class containing such an operator delete() and virtual dtor is indirectly and non-virtually multiply derived from, even though there is only one function instance. This is due to the current lookup rules. For example: struct B { virtual ~B(); void operator delete(void*);}; struct L : B {}; struct R : B {}; struct D: L,R {}; delete (B*)(L*)new D; Resolution: Requestor: John Max Skaller Owner: Steve Adamczyk (Name Look Up) Emails: Papers: N0322 = 93-0115 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 450 Title: How is operator new/delete looked up? Section: 12.5 [class.free] Free Store Status: active Description: [class.free] says: 2 When a non-array object or an array of class T is created by a new- expression, the allocation function is looked up in the scope of class T using the usual rules. Does that mean that operator new is looked up as a member of T and then in the current scope, or that it is looked up as a member of T and then in the enclosing scope of T? In other words, is this code well-formed? struct A { }; struct B { char buf[sizeof (A)]; void *operator new (size_t, void *p, int) { return p; } B() { new (buf, 1) A; } }; How about this? namespace foo { void *operator new (size_t, void *p, int) { return p; } struct A { }; } namespace bar { struct B { char buf[sizeof (foo::A)]; B() { new (buf, 1) foo::A; } }; } Resolution: Requestor: Jason Merrill Owner: Steve Adamczyk (Name Look Up) Emails: core-4749 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 138 (WMM.89) Title: When are default ctor default args evaluated for array elements? Section: 12.6 [class.init] Initialization Status: active Description: From Mike Miller's list of issues. WMM.89. Are default constructor arguments evaluated for each element of an array or just once for the entire array? int count = 0; class T { int i; public: T ( int j = count++ ) : i ( j ) {} ~T () { printf ( "%d,%d\n", i, count ); } }; T arrayOfTs[ 4 ]; Should this produce the output :- 0,4 1,4 2,4 3,4 or should it produce :- 0,1 0,1 0,1 0,1 Resolution: Requestor: Mike Miller / Martin O'Riordan Owner: Josee Lajoie (Construction) Emails: core-668 Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 298 Title: When and why is an expression-list optional in a mem-initializer Section: 12.6.2 [class.base.init] Initializing Bases and Members Status: active Description: 12.6.2p17 (syntax rule) says expression-list is optional. Is there an implied rule that says that omission of expression-list is allowed only when the base or member being initialized has a default constructor? (If so, this rule needs to be stated explicitly.) Or, alternatively, is there an implied requirement that any base or member (even a basic type) can be initialized with an empty expression-list? (If so, the semantics need to be defined.) Resolution: Requestor: Tom Plum / Dan Saks Owner: Josee Lajoie (Construction) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 359 Title: Timing of Evaluations in Base and Member Initializations Section: 12.6.2 [class.base.init] Initializing Bases and Members Status: active Description: Section 12.6.2 describes the order in which the members and base class parts of an object of class type are initialized. It does not, however, specify when the expressions used in the "mem-initializers" are to be evaluated. Consider this example: struct S { int i; int j; S() : i(0), j(i) {} }; 12.6.2/1 requires that i be initialized before j. But it seems to permit this order of execution: - Fetch the (uninitialized) value of i - Initialize i to 0 - Initialize j to the previously fetched value of i which is probably not what the programmer intended. Here, there is no function call (constructor call) to initialize the member i, is there none-the-less a sequence point after i is initialized? I would suggest adding words similar to: The expressions in the expression-list part of a mem-initializer are evaluated (including all side effects) immediately before the corresponding initialization is performed. When one base class or member is initialized before another base class or member, the expressions used in the mem-initializer for the second are evaluated (including all side effects) after the first initialization is performed. Resolution: Requestor: Patrick Smith Owner: Josee Lajoie (Construction) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 406b Title: Can a ctor-initializer initialize twice the same member? Section: 12.6.2 [class.base.init] Initializing Base and Members Status: active Description: There seems to be no overt restriction against specifying more than one mem-initializer for any given base or member in the list of mem-initializers for a given derived class constructor. Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Construction) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 95 Title: Volatility, copy constructors, and assignment operators. Section: 12.8 [class.copy] Status: active Description: It appears that volatile qualification has been overlooked in the specification of copy constructors and assignment operators. Section 12.1p5 of the WP says: "A copy constructor for a class X is a constructor whose first argument is of type X& or const X&..." But a user should be able to pass volatile objects (by reference) to copy constructors and/or assignment operators. In such cases it would be useful (and symmetric with const qualification) if: (a) these objects could be used as arguments to copy constructors and assignment operators, and (b) if the volatility associated with the types of the objects were preserved in the process. Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Class Copy) Emails: core-1653 Papers: See paper 94-0193R1/N0580R1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Issue Number: 306 Title: Does generated assignment require lvalue left-hand operand? Section: 12.8 [class.copy] Copying Class Objects Status: active Description: 12.8p?? It is nowhere mentioned whether the generated assignment requires an lvalue left-hand-side operand. One might assume it doesn't, except that some popular compilers assume that it does. Resolution: Requestor: Tom Plum / Dan Saks Owner: Tom Plum (lvalues) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 380 Title: What conditions cause an operator= to be generated? Section: 12.8 [class.copy] Copying Class Objects Status: active Description: Section 12.8/1 and section 13.4.3/1 of the working paper both note that an operator= will be generated for a class type if one is not explicitly declared/defined by the programmer. Must an implementation generate a member such as X& X::operator=(Q X&) for a class type `X' (where `Q' is some set of qualifiers determined by the rules given in 12.8/3) whenever the class type `X' fails to contain an explicit declaration for EXACTLY such a member, or is such a member generated only when the class type `X' contains absolutely no explicit declarations of ANY `operator='? struct S { S& operator= (int); }; struct S object1, object2; void caller () { object1 = object2; // ok? } Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Class Copy) Emails: Papers: See paper 94-0193R1/N0580R1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Work Group: Core Language Issue Number: 381 Title: May operator= be declared as `virtual'? Section: 12.8 [class.copy] Status: active Description: Section 12.8 of the working paper says that operator= is not inherited. Does this imply that an implementation is obliged to issue a diagnostic if an attempt is made to declare an operator= as virtual? If not, are the semantics of calls to virtual operator='s the same as those for other virtual functions even though these operators are "not inherited"? struct B { virtual int operator= (int) { return 1; } // ok? }; struct D : public B { virtual int operator= (int) { return 0; } // ok? }; D D_object; B *B_ptr = &D_object; int main () { int result1, result2; result1 = (B_ptr->operator=(99)); result2 = (*B_ptr = 99); return (result1+result2); } Must `main' exit with a zero exit status? Resolution: Requestor: Ron Guilmette Owner: Josee Lajoie (Class Copy) Emails: Papers: See paper 94-0193R1/N0580R1 ============================================================================== Chapter 13 - Overloading -------------------------- Work Group: Core Issue Number: 451 Title: Description of a call to a member function through a pointer to member is missing Section: 13.2.1.1.1 [over.call.func] Call to named function Status: active Description: Should this section also describe calls to member functions using the pointer to member syntax (.*, ->*) ? Resolution: Requestor: Owner: Steve Adamczyk (function overload resolution) Emails: Papers: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .