______________________________________________________________________

  7   Declarations                                   [dcl.dcl]

  ______________________________________________________________________

1 Declarations specify how names are to  be  interpreted.   Declarations
  have the form
          declaration-seq:
                  declaration
                  declaration-seq declaration
          declaration:
                  block-declaration
                  function-definition
                  template-declaration
                  linkage-specification
                  namespace-definition
          block-declaration:
                  simple-declaration
                  asm-definition
                  namespace-alias-definition
                  using-declaration
                  using-directive
          simple-declaration:
                  decl-specifier-seqopt init-declarator-listopt ;
  [Note:  asm-definitions  are  described  in  _dcl.asm_,  and  linkage-
  specifications are described in _dcl.link_.  Function-definitions  are
  described  in _dcl.fct.def_ and template-declarations are described in
  _temp_.   Namespace-definitions  are  described  in   _namespace.def_,
  using-declarations  are  described  in  _namespace.udecl_  and  using-
  directives  are  described  in  _namespace.udir_.    ]   The   simple-
  declaration
          decl-specifier-seqopt init-declarator-listopt ;
  is  divided into two parts: decl-specifiers, the components of a decl-
  specifier-seq, are described in _dcl.spec_ and declarators, the compo­
  nents of an init-declarator-list, are described in _dcl.decl_.

2 A  declaration  occurs in a scope (_basic.scope_); the scope rules are
  summarized in _basic.lookup_.  A declaration that declares a  function
  or  defines  a class, namespace, template, or function also has one or
  more scopes nested within it. These nested scopes, in turn,  can  have
  declarations  nested  within them. Unless otherwise stated, utterances
  in this clause about components in, of, or contained by a  declaration
  or subcomponent thereof refer only to those components of the declara­
  tion that are not nested within scopes nested within the  declaration.

3 In  a  simple-declaration,  the  optional  init-declarator-list can be
  omitted  only  when  declaring  a  class  (_class_)   or   enumeration
  (_dcl.enum_),  that  is, when the decl-specifier-seq contains either a

  class-specifier,  an  elaborated-type-specifier   with   a   class-key
  (_class.name_),  or  an enum-specifier.  In these cases and whenever a
  class-specifier or enum-specifier is present  in  the  decl-specifier-
  seq,  the  identifiers  in  these specifiers are among the names being
  declared by the declaration (as class-names, enum-names,  or  enumera­
  tors,  depending  on  the  syntax).  In such cases, and except for the
  declaration of an unnamed bit-field (_class.bit_), the decl-specified-
  seq shall introduce one or more names into the program, or shall rede­
  clare a name introduced by a previous declaration.  [Example:
          enum { };          // ill-formed
          typedef class { }; // ill-formed
   --end example]

4 Each init-declarator in the init-declarator-list contains exactly  one
  declarator-id,  which is the name declared by that init-declarator and
  hence one of  the  names  declared  by  the  declaration.   The  type-
  specifiers  (_dcl.type_)  in  the decl-specifier-seq and the recursive
  declarator  structure  of  the   init-declarator   describe   a   type
  (_dcl.meaning_), which is then associated with the name being declared
  by the init-declarator.

5 If the decl-specifier-seq contains the typedef specifier, the declara­
  tion  is  called  a  typedef  declaration  and  the name of each init-
  declarator is declared to be a typedef-name, synonymous with its asso­
  ciated  type  (_dcl.typedef_).   If the decl-specifier-seq contains no
  typedef specifier, the declaration is called a function declaration if
  the  type  associated with the name is a function type (_dcl.fct_) and
  an object declaration otherwise.

6 Syntactic components beyond those found in the general form of  decla­
  ration  are  added  to  a  function  declaration  to  make a function-
  definition.  An object declaration,  however,  is  also  a  definition
  unless  it  contains  the  extern  specifier  and  has  no initializer
  (_basic.def_).  A definition causes the appropriate amount of  storage
  to  be  reserved and any appropriate initialization (_dcl.init_) to be
  done.

7 Only in function declarations for constructors, destructors, and  type
  conversions can the decl-specifier-seq be omitted.1)

  7.1  Specifiers                                             [dcl.spec]

1 The specifiers that can be used in a declaration are
          decl-specifier:
                  storage-class-specifier
                  type-specifier
                  function-specifier
                  friend
                  typedef
          decl-specifier-seq:
                  decl-specifier-seqopt decl-specifier
  _________________________
  1) The "implicit int" rule of C is no longer supported.

2 The  longest sequence of decl-specifiers that could possibly be a type
  name is  taken  as  the  decl-specifier-seq  of  a  declaration.   The
  sequence shall be self-consistent as described below.  [Example:
          typedef char* Pc;
          static Pc;              // error: name missing
  Here,  the  declaration  static  Pc  is ill-formed because no name was
  specified for the static variable of type Pc.  To get  a  variable  of
  type  int called Pc, the type-specifier int has to be present to indi­
  cate that the typedef-name Pc is the name being  (re)declared,  rather
  than being part of the decl-specifier sequence.  For another example,
          void f(const Pc);       // void f(char* const)  (not const char*)
          void g(const int Pc);   // void g(const int)
   --end example]

3 [Note: since signed, unsigned, long, and short by default imply int, a
  type-name appearing after one of those specifiers is  treated  as  the
  name being (re)declared.  [Example:
          void h(unsigned Pc);       // void h(unsigned int)
          void k(unsigned int Pc);   // void k(unsigned int)
   --end example]  --end note]

  7.1.1  Storage class specifiers                              [dcl.stc]

1 The storage class specifiers are
          storage-class-specifier:
                  auto
                  register
                  static
                  extern
                  mutable
  At  most  one  storage-class-specifier  shall  appear in a given decl-
  specifier-seq.   If  a  storage-class-specifier  appears  in  a  decl-
  specifier-seq,  there  can  be  no typedef specifier in the same decl-
  specifier-seq and the init-declarator-list of  the  declaration  shall
  not  be  empty  (except  for  global  anonymous unions, which shall be
  declared static (_class.union_).  The storage-class-specifier  applies
  to  the  name  declared by each init-declarator in the list and not to
  any names declared by other specifiers.

2 The auto or register specifiers  can  be  applied  only  to  names  of
  objects  declared  in a block (_stmt.block_) or to function parameters
  (_dcl.fct.def_).  They specify that the  named  object  has  automatic
  storage  duration  (_basic.stc.auto_).   An  object declared without a
  storage-class-specifier at block  scope  or  declared  as  a  function
  parameter  has automatic storage duration by default.  Hence, the auto
  specifier is almost always redundant and not often used;  one  use  of
  auto  is  to  distinguish  a declaration-statement from an expression-
  statement (_stmt.expr_) explicitly.

3 A register specifier has the  same  semantics  as  an  auto  specifier
  together with a hint to the implementation that the object so declared
  will be heavily used.  The hint can be ignored and in most implementa­
  tions it will be ignored if the address of the object is taken.

4 The static specifier can be applied only to names of objects and func­
  tions and to anonymous unions (_class.union_).  There can be no static
  function  declarations within a block, nor any static function parame­
  ters.  A static  specifier  used  in  the  declaration  of  an  object
  declares    the    object    to    have    static   storage   duration
  (_basic.stc.static_).  A static specifier can be used in  declarations
  of  class members; _class.static_ describes its effect.  For the link­
  age of a name declared with a static specifier, see _basic.link_.  For
  a  nonmember  function,  an inline specifier is equivalent to a static
  specifier for linkage purposes (_basic.link_) unless the inline decla­
  ration  explicitly  includes  extern  as part of its decl-specifier or
  matches a previous declaration of the  function,  in  which  case  the
  function name retains the linkage of the previous declaration.

5 The  extern  specifier can be applied only to the names of objects and
  functions.  The extern specifier cannot be used in the declaration  of
  class  members  or  function  parameters.   For  the linkage of a name
  declared with an extern specifier, see _basic.link_.

6 A name declared in a namespace scope without a storage-class-specifier
  has  external linkage unless it has internal linkage because of a pre­
  vious declaration and provided it  is  not  declared  const.   Objects
  declared  const and not explicitly declared extern have internal link­
  age.

7 The linkages implied by successive declarations  for  a  given  entity
  shall  agree.  That is, within a given scope, each declaration declar­
  ing the same object name or the same overloading of  a  function  name
  shall  imply  the same linkage.  Each function in a given set of over­
  loaded functions can have a different linkage, however.  [Example:
          static char* f(); // f() has internal linkage
          char* f()         // f() still has internal linkage
              { /* ... */ }
          char* g();        // g() has external linkage
          static char* g()  // error: inconsistent linkage
              { /* ... */ }
          void h();
          inline void h();  // external linkage
          inline void l();
          void l();         // internal linkage
          inline void m();
          extern void m();  // internal linkage
          static void n();
          inline void n();  // internal linkage
          static int a;     // `a' has internal linkage
          int a;            // error: two definitions
          static int b;     // `b' has internal linkage
          extern int b;     // `b' still has internal linkage
          int c;            // `c' has external linkage
          static int c;     // error: inconsistent linkage
          extern int d;     // `d' has external linkage
          static int d;     // error: inconsistent linkage
   --end example]

8 The name of a declared but undefined class can be used  in  an  extern
  declaration.   Such  a declaration, however, cannot be used before the
  class has been defined.  [Example:
          struct S;
          extern S a;
          extern S f();
          extern void g(S);

          void h()
          {
              g(a);       // error: S undefined
              f();        // error: S undefined
          }
   --end example] The mutable specifier can be applied only to names  of
  class  data  members  (_class.mem_)  and  can  not be applied to names
  declared const or static.  [Example:
          class X {
                  mutable const int* p;   // ok
                  mutable int* const q;   // ill-formed
          };
   --end example]

9 The mutable specifier on a class data member nullifies a const  speci­
  fier  applied  to the containing class object and permits modification
  of the mutable class member even though the  rest  of  the  object  is
  const (_dcl.type.cv_).

  7.1.2  Function specifiers                              [dcl.fct.spec]

1 Function-specifiers can be used only in function declarations.
          function-specifier:
                  inline
                  virtual
                  explicit

2 A  function declaration (_dcl.fct_, _class.mfct_, _class.friend_) with
  an inline specifier declares an inline function.  The inline specifier
  indicates  to the implementation that inline substitution of the func­
  tion body at the point of call is to be preferred to the  usual  func­
  tion  call  mechanism.   An  implementation is not required to perform
  this inline substitution at the point of call; however, even  if  this
  inline  substitution  is omitted, the other rules for inline functions
  defined by this subclause shall still be respected.

3 A function defined within a class definition is  an  inline  function.
  The inline specifier shall not appear on a block scope function decla­
  ration.  For the linkage of inline  functions,  see  _basic.link_  and
  _dcl.stc_.

4 An inline function shall be defined in every translation unit in which
  it is used (_basic.def.odr_), and shall have exactly the same  defini­
  tion  in  every  case (see one definition rule, _basic.def.odr_). If a
  function with external linkage is declared inline in  one  translation

  unit, it shall be declared inline in all translation units in which it
  appears.  [Note: a static local variable in an extern inline  function
  always refers to the same object.  ]

5 The  virtual specifier shall be used only in declarations of nonstatic
  class   member   functions   within   a   class    declaration;    see
  _class.virtual_.

6 The explicit specifier shall be used only in declarations of construc­
  tors within a class declaration; see _class.conv.ctor_.

  7.1.3  The typedef specifier                             [dcl.typedef]

1 Declarations containing the decl-specifier typedef declare identifiers
  that can be used later for naming fundamental (_basic.fundamental_) or
  compound (_basic.compound_) types.  The typedef specifier shall not be
  used  in  a  function-definition  (_dcl.fct.def_), and it shall not be
  combined in a decl-specifier-seq with  any  other  kind  of  specifier
  except a type-specifier.
          typedef-name:
                  identifier
  A  name  declared  with  the typedef specifier becomes a typedef-name.
  Within the scope of its declaration, a typedef-name  is  syntactically
  equivalent to a keyword and names the type associated with the identi­
  fier in the way described in _dcl.decl_.  A  typedef-name  is  thus  a
  synonym  for  another  type.   A typedef-name does not introduce a new
  type the way a class declaration (_class.name_)  or  enum  declaration
  does.  [Example: after
          typedef int MILES, *KLICKSP;
  the constructions
          MILES distance;
          extern KLICKSP metricp;
  are  all  correct  declarations;  the type of distance is int; that of
  metricp is "pointer to int."  ]

2 In a given scope, a typedef specifier can be used to redefine the name
  of  any  type  declared in that scope to refer to the type to which it
  already refers.  [Example:
          typedef struct s { /* ... */ } s;
          typedef int I;
          typedef int I;
          typedef I I;
   --end example]

3 In a given scope, a typedef specifier shall not be  used  to  redefine
  the  name  of  any type declared in that scope to refer to a different
  type.  [Example:
          class complex { /* ... */ };
          typedef int complex;    // error: redefinition
   --end example] Similarly, in a given scope, a  class  or  enumeration
  shall  not  be  declared  with the same name as a typedef-name that is
  declared in that scope and refers to a type other than  the  class  or
  enumeration itself.  [Example:

          typedef int complex;
          class complex { /* ... */ };  // error: redefinition
   --end example]

4 A typedef-name that names a class is a class-name (_class.name_).  The
  typedef-name shall not be used after a class, struct, or union  prefix
  and not in the names for constructors and destructors within the class
  declaration itself.  [Example:
          struct S {
              S();
              ~S();
          };

          typedef struct S T;

          S a = T();      // ok
          struct T * p;   // error
   --end example]

5 If the typedef declaration defines an unnamed  class  (or  enum),  the
  first  typedef-name  declared by the declaration to be that class type
  (or enum type) is used to denote the class type  (or  enum  type)  for
  linkage purposes only (_basic.link_).  [Example:
          typedef struct { } *ps, S; // 'S' is the class name for linkage purposes
    --end  example]  If  the typedef-name is used where a class-name (or
  enum-name) is required, the program is ill-formed.  [Example:
          typedef struct {
              S();    // error: requires a return type since S is
                      // an ordinary member function, not a constructor
          } S;
   --end example]

  7.1.4  The friend specifier                               [dcl.friend]

1 The friend specifier is used to specify access to class  members;  see
  _class.friend_.

  7.1.5  Type specifiers                                      [dcl.type]

1 The type-specifiers are
          type-specifier:
                  simple-type-specifier
                  class-specifier
                  enum-specifier
                  elaborated-type-specifier
                  cv-qualifier
  As  a  general rule, at most one type-specifier is allowed in the com­
  plete decl-specifier-seq of a declaration.   The  only  exceptions  to
  this rule are the following:

2
  --const  or  volatile  can  be combined with any other type-specifier.
    However,  redundant  cv-qualifiers  are   prohibited   except   when

    introduced  through  the use of typedefs (_dcl.typedef_) or template
    type  arguments  (_temp.arg_),  in  which  case  the  redundant  cv-
    qualifiers are ignored.

  --signed or unsigned can be combined with char, long, short, or int.

  --short or long can be combined with int.

  --long can be combined with double.

3 At  least one type-specifier that is not a cv-qualifier is required in
  a typedef declaration.  At least one type-specifier that is not a  cv-
  qualifier  is  required in a function declaration unless it declares a
  constructor, destructor or type conversion operator.2)

4 [Note: class-specifiers and enum-specifiers are discussed  in  _class_
  and  _dcl.enum_, respectively.  The remaining type-specifiers are dis­
  cussed in the rest of this section.  ]

  7.1.5.1  The cv-qualifiers                               [dcl.type.cv]

1 There are two cv-qualifiers, const and volatile.   If  a  cv-qualifier
  appears  in a decl-specifier-seq, the init-declarator-list of the dec­
  laration shall not be empty.  [Note: _basic.type.qualifier_  describes
  how cv-qualifiers affect object and function types.  ]

2 Unless  explicitly  declared  extern, an object declared with a const-
  qualified  type  has  internal  linkage  and  shall   be   initialized
  (_dcl.init_,  _class.ctor_).  For an object of const-qualified type T,
  if no explicit initializer is specified to initialize the object,  and
  T is a class with an explicitly declared default constructor, the con­
  structor for T is called; otherwise, the program  is  ill-formed.   An
  integral  or enumeration object of const-qualified type initialized by
  an integral constant expression  can  be  used  in  integral  constant
  expressions (_expr.const_).

3 A  pointer or reference to a cv-qualified type need not actually point
  or refer to a cv-qualified object, but it is treated as if it does;  a
  const-qualified access path cannot be used to modify an object even if
  the object referenced is  a  non-const  object  and  can  be  modified
  through some other access path.  [Note: cv-qualifiers are supported by
  the type system so that  they  cannot  be  subverted  without  casting
  (_expr.const.cast_).  ]

4 Except that any class member declared mutable (_dcl.stc_) can be modi­
  fied, any attempt  to  modify  a  const  object  during  its  lifetime
  (_basic.life_) results in undefined behavior.

  _________________________
  2) There is no special provision for a decl-specifier-seq that lacks a
  type-specifier  or  that  has a type-specifier that only specifies cv-
  qualifiers.  The "implicit int" rule of C is no longer supported.

5 [Example:
          const int ci = 3;  // cv-qualified (initialized as required)
          ci = 4;            // ill-formed: attempt to modify const
          int i = 2;         // not cv-qualified
          const int* cip;    // pointer to const int
          cip = &i;          // okay: cv-qualified access path to unqualified
          *cip = 4;          // ill-formed: attempt to modify through ptr to const
          int* ip;
          ip = const_cast<int*>(cip); // cast needed to convert const int* to int*
          *ip = 4;           // defined: *ip points to i, a non-const object
          const int* ciq = new const int (3); // initialized as required
          int* iq = const_cast<int*>(ciq);    // cast required
          *iq = 4;           // undefined: modifies a const object

6 For another example
          class X {
              public:
                  mutable int i;
                  int j;
          };
          class Y {
              public:
                  X x;
                  Y();
          };
          const Y y;
          y.x.i++;        // well-formed: mutable member can be modified
          y.x.j++;        // ill-formed: const-qualified member modified
          Y* p = const_cast<Y*>(&y);      // cast away const-ness of y
          p->x.i = 99;    // well-formed: mutable member can be modified
          p->x.j = 99;    // undefined: modifies a const member
   --end example]

7 [Note:  volatile  is  a hint to the implementation to avoid aggressive
  optimization involving the object because  the  value  of  the  object
  might  be  changed  by  means  undetectable by an implementation.  See
  _intro.execution_ for detailed semantics.  In general,  the  semantics
  of volatile are intended to be the same in C++ as they are in C.  ]

  7.1.5.2  Simple type specifiers                      [dcl.type.simple]

1 The simple type specifiers are

          simple-type-specifier:
                  ::opt nested-name-specifieropt type-name
                  char
                  wchar_t
                  bool
                  short
                  int
                  long
                  signed
                  unsigned
                  float
                  double
                  void
          type-name:
                  class-name
                  enum-name
                  typedef-name
  The  simple-type-specifiers specify either a previously-declared user-
  defined type or one of the  fundamental  types  (_basic.fundamental_).
  Table  1  summarizes  the valid combinations of simple-type-specifiers
  and the types they specify.

        Table 1--simple-type-specifiers and the types they specify

               +-------------------+----------------------+
               |Specifier(s)       | Type                 |
               +-------------------+----------------------+
               |type-name          | the type named       |
               |char               | "char"               |
               |unsigned char      | "unsigned char"      |
               |signed char        | "signed char"        |
               |bool               | "bool"               |
               |unsigned           | "unsigned int"       |
               |unsigned int       | "unsigned int"       |
               |signed             | "int"                |
               |signed int         | "int"                |
               |int                | "int"                |
               |unsigned short int | "unsigned short int" |
               |unsigned short     | "unsigned short int" |
               |unsigned long int  | "unsigned long int"  |
               |unsigned long      | "unsigned long int"  |
               |signed long int    | "long int"           |
               |signed long        | "long int"           |
               |long int           | "long int"           |
               |long               | "long int"           |
               |signed short int   | "short int"          |
               |signed short       | "short int"          |
               |short int          | "short int"          |
               |short              | "short int"          |
               |wchar_t            | "wchar_t"            |
               |float              | "float"              |
               |double             | "double"             |
               |long double        | "long double"        |
               |void               | "void"               |
               +-------------------+----------------------+
  When multiple simple-type-specifiers are allowed, they can  be  freely
  intermixed with other decl-specifiers in any order.  It is implementa­
  tion-defined whether bit-fields and objects of char  type  are  repre­
  sented  as signed or unsigned quantities.  The signed specifier forces
  char objects and bit-fields to be signed; it is redundant  with  other
  integral types.

  7.1.5.3  Elaborated type specifiers                    [dcl.type.elab]

1         elaborated-type-specifier:
                  class-key ::opt nested-name-specifieropt identifier
                  enum ::opt nested-name-specifieropt identifier

2 If  an elaborated-type-specifier is the sole constituent of a declara­
  tion, the declaration is ill-formed unless it is an explicit  special­
  ization      (_temp.expl.spec_),     an     explicit     instantiation
  (_temp.explicit_) or it has one of the following forms:

  --      class-key identifier ;

3 --      friend class-key identifier ;

4 --      friend class-key ::identifier ;
          friend class-key nested-name-specifier identifier ;

5 _basic.lookup.elab_ describes how name look up proceeds for the  iden­
  tifier in an elaborated-type-specifier.  If the identifier resolves to
  a class-name or enum-name, the elaborated-type-specifier introduces it
  into  the  declaration the same way a simple-type-specifier introduces
  its type-name.  If the identifier resolves to a typedef-name or a tem­
  plate type-parameter, the elaborated-type-specifier is ill-formed.  If
  name look up does not find a declaration for the name, the elaborated-
  type-specifier is ill-formed unless it is of the simple form class-key
  identifier in which case the identifier is declared  as  described  in
  _basic.scope.pdecl_.

6 The class-key or enum keyword present in the elaborated-type-specifier
  shall agree in kind with the declaration to  which  the  name  in  the
  elaborated-type-specifier  refers.  This rule also applies to the form
  of elaborated-type-specifier that  declares  a  class-name  or  friend
  class  since it can be construed as referring to the definition of the
  class.  Thus, in any elaborated-type-specifier, the enum keyword shall
  be  used  to refer to an enumeration (_dcl.enum_), the union class-key
  shall be used to refer to a union (_class_), and either the  class  or
  struct  class-key shall be used to refer to a class (_class_) declared
  using the class or struct class-key.

  7.2  Enumeration declarations                               [dcl.enum]

1 An enumeration is a distinct  type  (_basic.fundamental_)  with  named
  constants.  Its name becomes an enum-name, within its scope.
          enum-name:
                  identifier
          enum-specifier:
                  enum identifieropt { enumerator-listopt }
          enumerator-list:
                  enumerator-definition
                  enumerator-list , enumerator-definition
          enumerator-definition:
                  enumerator
                  enumerator = constant-expression
          enumerator:
                  identifier
  The  identifiers  in an enumerator-list are declared as constants, and
  can  appear  wherever  constants  are  required.   If  no  enumerator-
  definitions  with  = appear, then the values of the corresponding con­
  stants begin at zero and increase by one  as  the  enumerator-list  is
  read  from  left  to right.  An enumerator-definition with = gives the

  associated enumerator the value indicated by the  constant-expression;
  subsequent  enumerators  without initializers continue the progression
  from the assigned value.  The constant-expression shall be of integral
  or enumeration type.

2 [Example:
          enum { a, b, c=0 };
          enum { d, e, f=e+2 };
  defines a, c, and d to be zero, b and e to be 1, and f to be 3.  ]

3 The  point  of  declaration for an enumerator is immediately after its
  enumerator-definition.  [Example:
          const int x = 12;
          { enum { x = x }; }
  Here, the enumerator x is initialized with the value of  the  constant
  x, namely 12.  ]

4 Each  enumeration  defines  a  type  that  is different from all other
  types.  The type of an enumerator is its enumeration.

5 The underlying type of an enumeration is an  integral  type  that  can
  represent all the enumerator values defined in the enumeration.  It is
  implementation-defined which integral type is used as  the  underlying
  type  for  an enumeration except that the underlying type shall not be
  larger than int unless the value of an enumerator cannot fit in an int
  or unsigned int.  If the enumerator-list is empty, the underlying type
  is as if the enumeration had a single enumerator with  value  0.   The
  value of sizeof() applied to an enumeration type, an object of enumer­
  ation type, or an enumerator, is the value of sizeof() applied to  the
  underlying type.

6 For  an  enumeration where emin is the smallest enumerator and emax is
  the largest, the values of the  enumeration  are  the  values  of  the
  underlying  type  in  the range bmin to bmax, where bmin and bmax are,
  respectively, the smallest and largest values  of  the  smallest  bit-
  field that can store emin and emax.3) It is possible to define an enu­
  meration that has values not defined by any of its enumerators.

7 Two enumeration types are layout-compatible  if  they  have  the  same
  underlying type.

8 The value of an enumerator or an object of an enumeration type is con­
  verted to an integer by integral promotion (_conv.prom_).  [Example:
      enum color { red, yellow, green=20, blue };
      color col = red;
      color* cp = &col;
      if (*cp == blue) // ...
  makes color a type describing various colors, and then declares col as
  _________________________
  3)  On  a two's-complement machine, bmax is the smallest value greater
  than or equal to max(abs(emin)-1,abs(emax)) of the form 2M-1; bmin  is
  zero if emin is non-negative and -(bmax+1) otherwise.

  an object of that type, and cp as a pointer to an object of that type.
  The possible values of an object of type color are red, yellow, green,
  blue;  these  values can be converted to the integral values 0, 1, 20,
  and 21.  Since enumerations are distinct types, objects of type  color
  can be assigned only values of type color.
          color c = 1;     // error: type mismatch,
                           // no conversion from int to color
          int i = yellow;  // ok: yellow converted to integral value 1
                           // integral promotion
  See also _diff.anac_.  ]

9 An expression of arithmetic or enumeration type can be converted to an
  enumeration type explicitly.  The value is unchanged if it is  in  the
  range  of  enumeration  values  of the enumeration type; otherwise the
  resulting enumeration value is unspecified.

10The enum-name and each enumerator declared  by  an  enum-specifier  is
  declared  in  the  scope that immediately contains the enum-specifier.
  These  names  obey  the  scope  rules  defined  for   all   names   in
  (_basic.scope_) and (_basic.lookup_).  An enumerator declared in class
  scope can be referred to using the class member access operators ::, .
  (dot) and -> (arrow)), see _expr.ref_.  [Example:
          class X {
          public:
              enum direction { left='l', right='r' };
              int f(int i)
                  { return i==left ? 0 : i==right ? 1 : 2; }
          };
          void g(X* p)
          {
              direction d;        // error: `direction' not in scope
              int i;
              i = p->f(left);     // error: `left' not in scope
              i = p->f(X::right); // ok
              i = p->f(p->left);  // ok
              // ...
          }
   --end example]

  7.3  Namespaces                                      [basic.namespace]

1 A  namespace is an optionally-named declarative region.  The name of a
  namespace can be used to access entities declared in  that  namespace;
  that  is,  the  members  of  the  namespace.  Unlike other declarative
  regions, the definition of a namespace can be split over several parts
  of one or more translation units.

2 A  name  declared  outside all named namespaces, blocks (_stmt.block_)
  and    classes    (_class_)     has     global     namespace     scope
  (_basic.scope.namespace_).

  7.3.1  Namespace definition                            [namespace.def]

1 The grammar for a namespace-definition is
          namespace-name:
                  original-namespace-name
                  namespace-alias
          original-namespace-name:
                  identifier

          namespace-definition:
                  named-namespace-definition
                  unnamed-namespace-definition

          named-namespace-definition:
                  original-namespace-definition
                  extension-namespace-definition

          original-namespace-definition:
                  namespace identifier { namespace-body }

          extension-namespace-definition:
                  namespace original-namespace-name  { namespace-body }

          unnamed-namespace-definition:
                  namespace { namespace-body }

          namespace-body:
                  declaration-seqopt

2 The identifier in an original-namespace-definition shall not have been
  previously defined in the declarative region in  which  the  original-
  namespace-definition   appears.    The   identifier  in  an  original-
  namespace-definition is the name of the  namespace.   Subsequently  in
  that  declarative region, it is treated as an original-namespace-name.

3 The original-namespace-name in an extension-namespace-definition shall
  have  previously  been  defined in an original-namespace-definition in
  the same declarative region.

4 Every namespace-definition shall appear in the global scope  or  in  a
  namespace scope (_basic.scope.namespace_).

5 Because a namespace-definition contains declarations in its namespace-
  body and a namespace-definition is itself a  declaration,  it  follows
  that namespace-definitions can be nested.  [Example:
          namespace Outer {
                  int i;
                  namespace Inner {
                          void f() { i++; } // Outer::i
                          int i;
                          void g() { i++; } // Inner::i
                  }
          }

   --end example]

  7.3.1.1  Unnamed namespaces                        [namespace.unnamed]

1 An unnamed-namespace-definition behaves as if it were replaced by
          namespace unique { /* empty body */ }
          using namespace unique;
          namespace unique { namespace-body }
  where,  for  each  translation unit, all occurrences of unique in that
  translation unit are replaced by an identifier that differs  from  all
  other identifiers in the entire program.4) [Example:
          namespace { int i; }       // unique::i
          void f() { i++; }          // unique::i++

          namespace A {
                  namespace {
                          int i;     // A::unique::i
                          int j;     // A::unique::j
                  }
                  void g() { i++; }  // A::unique::i++
          }
          using namespace A;
          void h() {
                  i++;               // error: unique::i or A::unique::i
                  A::i++;            // A::unique::i
                  j++;               // A::unique::j
          }
   --end example]

2 The use of the static keyword is deprecated when declaring objects  in
  a namespace scope (see Annex _depr_); the unnamed-namespace provides a
  superior alternative.

  7.3.1.2  Namespace member definitions               [namespace.memdef]

1 Members of a namespace can be defined within that  namespace.   [Exam­
  ple:
          namespace X {
                  void f() { /* ... */ }
          }
   --end example]

2 Members  of  a named namespace can also be defined outside that names­
  pace by explicit qualification (_namespace.qual_) of  the  name  being
  defined,  provided  that the entity being defined was already declared
  in the namespace and the definition appears after the point of  decla­
  ration  in  a  namespace  that  encloses  the declaration's namespace.
  _________________________
  4) Although entities in an unnamed namespace might have external link­
  age, they are effectively qualified by a name unique to their transla­
  tion  unit  and therefore can never be seen from any other translation
  unit.

  [Example:
          namespace Q {
                  namespace V {
                          void f();
                  }
                  void V::f() { /* ... */ }  // fine
                  void V::g() { /* ... */ }  // error: g() is not yet a member of V
                  namespace V {
                          void g();
                  }
          }
          namespace R {
                  void Q::V::g() { /* ... */ } // error: R doesn't enclose Q
          }
   --end example]

3 Every name first declared in a namespace is a member  of  that  names­
  pace.   A friend function first declared within a class is a member of
  the innermost enclosing namespace.  When looking for a prior  declara­
  tion of a class or a function declared as a friend, scopes outside the
  innermost enclosing namespace scope are not considered.  [Example:
          // Assume f and g have not yet been defined.
          friend void h(int);
          namespace A {
                  class X {
                          friend void f(X);  // declaration of f
                          class Y {
                                  friend void g();    // A::g is a friend
                                  friend void h(int); // A::h is a friend
                                                      // ::h not considered
                          };
                  };

                  void f(X) { /* ... */}     // definition of f declared above
                  X x;
                  void g() { f(x); }         // f and g are members of A
                  void h(int) { /* ... */ }  // h is a member of A
          }
          using A::x;

          void h()
          {
                  A::f(x);
                  A::X::f(x);    // error: f is not a member of A::X
                  A::X::Y::g();  // error: g is not a member of A::X::Y
          }
   --end example] The scope of class names first  introduced  in  elabo­
  rated-type-specifiers is described in (_basic.scope.pdecl_).

4 When  an  entity declared with a block scope extern declaration is not
  found to refer to some other declaration, then that entity is a member
  of the innermost enclosing namespace.  However such a declaration does
  not introduce the member name in its namespace scope.  [Example:

          namespace X {
                  void p()
                  {
                          q();              // error: q not yet declared
                          extern void q();  // q is a member of namespace X
                  }
                  void middle()
                  {
                          q();              // error: q not yet declared
                  }
                  void q() { /* ... */ }    // definition of X::q
          }

          void q() { /* ... */ }            // some other, unrelated q
   --end example]

  7.3.2  Namespace alias                               [namespace.alias]

1 A namespace-alias-definition declares an alternate name for  a  names­
  pace according to the following grammar:
          namespace-alias:
                  identifier

          namespace-alias-definition:
                  namespace identifier = qualified-namespace-specifier ;

          qualified-namespace-specifier:
                  ::opt nested-name-specifieropt namespace-name

2 The  identifier  in  a namespace-alias-definition is a synonym for the
  name of the namespace denoted by the qualified-namespace-specifier and
  becomes a namespace-alias.  [Note: when looking up a namespace-name in
  a namespace-alias-definition, only namespace names are considered, see
  _basic.lookup.udir_.  ]

3 In  a  declarative region, a namespace-alias-definition can be used to
  redefine a namespace-alias declared  in  that  declarative  region  to
  refer to the namespace to which it already refers.  [Example: the fol­
  lowing declarations are well-formed:
          namespace Company_with_very_long_name { /* ... */ }
          namespace CWVLN = Company_with_very_long_name;
          namespace CWVLN = Company_with_very_long_name;  // ok: duplicate
          namespace CWVLN = CWVLN;
   --end example]

4 A namespace-name or namespace-alias shall not be declared as the  name
  of  any other entity in the same declarative region.  A namespace-name
  defined at global scope shall not be declared as the name of any other
  entity  in any global scope of the program.  No diagnostic is required
  for a violation of this rule by declarations in different  translation
  units.

  7.3.3  The using declaration                         [namespace.udecl]

1 A  using-declaration  introduces a name into the declarative region in
  which the using-declaration appears.  That name is a synonym  for  the
  name  of some entity declared elsewhere.  A name specified in a using-
  declaration in a class or namespace scope shall not already be a  mem­
  ber of that scope.
          using-declaration:
                  using typenameopt ::opt nested-name-specifier unqualified-id ;
                  using ::  unqualified-id ;

2 The  member names specified in a using-declaration are declared in the
  declarative region in which the using-declaration appears.

3 Every using-declaration is a declaration and a member-declaration  and
  so can be used in a class definition.  [Example:
          struct B {
                  void f(char);
                  void g(char);
          };
          struct D : B {
                  using B::f;
                  void f(int) { f('c'); } // calls B::f(char)
                  void g(int) { g('c'); } // recursively calls D::g(int)
          };
   --end example]

4 A using-declaration used as a member-declaration shall refer to a mem­
  ber of a base class of the class being defined.  [Example:
          class C {
                  int g();
          };
          class D2 : public B {
                  using B::f;  // ok: B is a base of D2
                  using C::g;  // error: C isn't a base of D2
          };
   --end example] [Note: since constructors and destructors do not  have
  names, a using-declaration cannot refer to a constructor or a destruc­
  tor for a base class.  ]

5 A using-declaration  for  a  member  shall  be  a  member-declaration.
  [Example:
          struct X {
                  int i;
                  static int s;
          };
          void f()
          {
                  using X::i;  // error: X::i is a class member
                               // and this is not a member declaration.
                  using X::s;  // error: X::s is a class member
                               // and this is not a member declaration.
          }

   --end example]

6 Members declared by a using-declaration can be referred to by explicit
  qualification just like other member names (_namespace.qual_).   In  a
  using-declaration, a prefix :: refers to the global namespace.  [Exam­
  ple:
          void f();

          namespace A {
                  void g();
          }
          namespace X {
                  using ::f;   // global f
                  using A::g;  // A's g
          }
          void h()
          {
                  X::f();      // calls ::f
                  X::g();      // calls A::g
          }
   --end example]

7 A using-declaration is a declaration and can therefore be used repeat­
  edly where (and only where) multiple declarations are allowed.  [Exam­
  ple:
          namespace A {
                  int i;
          }

          namespace A1 {
                  using A::i;
                  using A::i; // ok: double declaration
          }

          void f()
          {
                  using A::i;
                  using A::i; // error: double declaration
          }
          class B {
          public:
                  int i;
          };

          class X : public B {
                  using B::i;
                  using B::i;  // error: double member declaration
          };
   --end example]

8 The entity declared by a using-declaration shall be known in the  con­
  text  using  it according to its definition at the point of the using-
  declaration.  Definitions added to  the  namespace  after  the  using-

  declaration are not considered when a use of the name is made.  [Exam­
  ple:
          namespace A {
                  void f(int);
          }
          using A::f;              // f is a synonym for A::f;
                                   // that is, for A::f(int).
          namespace A {
                  void f(char);
          }
          void foo()
          {
                  f('a');          // calls f(int),
          }                        // even though f(char) exists.
          void bar()
          {
                  using A::f;      // f is a synonym for A::f;
                                   // that is, for A::f(int) and A::f(char).
                  f('a');          // calls f(char)
          }
   --end example]

9 A name defined by a using-declaration is an  alias  for  its  original
  declarations  so  that the using-declaration does not affect the type,
  linkage or other attributes of the members referred to.

10If 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

  --exactly one declaration shall declare a class  name  or  enumeration
    name  and  the other declarations shall all refer to the same entity
    or all refer to functions; in this case the class name  or  enumera­
    tion name is hidden (_basic.scope.hiding_).

11[Example:
          namespace A {
                  int x;
          }
          namespace B {
                  int i;
                  struct g { };
                  struct x { };
                  void f(int);
                  void f(double);
                  void g(char);   // OK: hides struct g
          }

          void func()
          {
                  int i;
                  using B::i;     // error: i declared twice
                  void f(char);
                  using B::f;     // fine: each f is a function
                  f(3.5);         // calls B::f(double)
                  using B::g;
                  g('a');         // calls B::g(char)
                  struct g g1;    // g1 has class type B::g
                  using B::x;
                  using A::x;     // fine: hides struct B::x
                  x = 99;         // assigns to A::x
                  struct x x1;    // x1 has class type B::x
          }
   --end example]

12If  a  function  declaration in namespace scope or block scope has the
  same name and the same parameter types as a function introduced  by  a
  using-declaration,  the  program  is  ill-formed.   [Note:  two using-
  declarations may introduce functions with the same name and  the  same
  parameter  types.  A call to such a function is ill-formed unless name
  look up can unambiguously select the function to  be  called  (because
  the function name is qualified by its namespace name, for example).  ]
  [Example:
          namespace C {
                  void f(int);
                  void f(double);
                  void f(char);
          }
          void h()
          {
                  using B::f;   // B::f(int) and B::f(double)
                  using C::f;   // C::f(int), C::f(double), and C::f(char)
                  f('h');       // calls C::f(char)
                  f(1);         // error: ambiguous: B::f(int) or C::f(int) ?
                  void f(int);  // error: f(int) conflicts with C::f(int)
          }
   --end example]

13When a using-declaration brings names from a base class into a derived
  class  scope,  member  functions  in the derived class override and/or
  hide virtual member functions with the same name and  parameter  types
  in a base class (rather than conflicting).  [Example:
          struct B {
                  virtual void f(int);
                  virtual void f(char);
                  void g(int);
                  void h(int);
          };

          struct D : B {
                  using B::f;
                  void f(int);   // ok: D::f(int) overrides B::f(int);

                  using B::g;
                  void g(char);  // ok

                  using B::h;
                  void h(int);   // ok: D::h(int) hides B::h(int)
          };
          void k(D* p)
          {
                  p->f(1);    // calls D::f(int)
                  p->f('a');  // calls B::f(char)
                  p->g(1);    // calls B::g(int)
                  p->g('a');  // calls D::g(char)
          }
    --end example] [Note: two using-declarations may introduce functions
  with the same name and the same parameter types.  A  call  to  such  a
  function  is  ill-formed  unless name look up can unambiguously select
  the function to be called (because the function name is  qualified  by
  its class name, for example).  ]

14For the purpose of overload resolution, the functions which are intro­
  duced by a using-declaration into a derived class will be  treated  as
  though  they  were  members  of the derived class.  In particular, the
  implicit this parameter shall be treated as if it were  a  pointer  to
  the  derived  class rather than to the base class.  This has no effect
  on the type of the function, and in all other  respects  the  function
  remains a member of the base class.

15All  instances  of  the name mentioned in a using-declaration shall be
  accessible.   In  particular,  if  a  derived  class  uses  a   using-
  declaration  to access a member of a base class, the member name shall
  be accessible.  If the name is that of an overloaded member  function,
  then all functions named shall be accessible.

16The alias created by the using-declaration has the usual accessibility
  for a member-declaration.  [Example:
          class A {
          private:
                  void f(char);
          public:
                  void f(int);
          protected:
                  void g();
          };
          class B : public A {
                  using A::f; // error: A::f(char) is inaccessible
          public:
                  using A::g; // B::g is a public synonym for A::g
          };
   --end example]

17[Note: use of access-declarations (_class.access.dcl_) is  deprecated;
  member using-declarations provide a better alternative.  ]

  7.3.4  Using directive                                [namespace.udir]

1         using-directive:
                  using  namespace ::opt nested-name-specifieropt namespace-name ;
  A  using-directive  shall not appear in class scope, but may appear in
  namespace scope or in block scope.  [Note: when looking  up  a  names­
  pace-name  in  a using-directive, only namespace names are considered,
  see _basic.lookup.udir_.  ]

2 A using-directive specifies that the names in the nominated  namespace
  can  be  used  in the scope in which the using-directive appears after
  the   using-directive.     During    unqualified    name    look    up
  (_basic.lookup.unqual_),  the names appear as if they were declared in
  the  nearest  enclosing  namespace  which  contains  both  the  using-
  directive  and the nominated namespace.  [Note: in this context, "con­
  tains" means "contains directly or indirectly".  ]  A  using-directive
  does  not  add  any  members  to  the  declarative  region in which it
  appears.  [Example:
          namespace A {
                  int i;
                  namespace B {
                          namespace C {
                                  int i;
                          }
                          using namespace A::B::C;
                          void f1() {
                                  i = 5; // ok, C::i visible in B and hides A::i
                          }
                  }
                  namespace D {
                          using namespace B;
                          using namespace C;
                          void f2() {
                                  i = 5; // ambiguous , B::C::i or A::i ?
                          }
                  }
                  void f3() {
                          i = 5; // uses A::i
                  }
          }
          void f4() {
                  i = 5;  // ill-formed; neither "i" is visible
          }
  ]

3 The using-directive is  transitive:  if  a  scope  contains  a  using-
  directive  that  nominates  a  second  namespace  that itself contains
  using-directives, the effect is as if the  using-directives  from  the
  second namespace also appeared in the first.  [Example:

          namespace M {
                  int i;
          }
          namespace N {
                  int i;
                  using namespace M;
          }
          void f()
          {
                  using namespace N;
                  i = 7;    // error: both M::i and N::i are visible
          }
  For another example,
          namespace A {
                  int i;
          }
          namespace B {
                  int i;
                  int j;
                  namespace C {
                          namespace D {
                                  using namespace A;
                                  int j;
                                  int k;
                                  int a = i;  // B::i hides A::i
                          }
                          using namespace D;
                          int k = 89; // no problem yet
                          int l = k;  // ambiguous: C::k or D::k;
                          int m = i;  // B::i hides A::i
                          int n = j;  // D::j hides B::j
                  }
          }
   --end example]

4 If a namespace is extended by an extended-namespace-definition after a
  using-directive is given,  the  additional  members  of  the  extended
  namespace can be used after the extended-namespace-definition.

5 If name look up finds a declaration for a name in two different names­
  paces, and the declarations do not declare the same entity and do  not
  declare  functions, the use of the name is ill-formed.  [Note: in par­
  ticular, the name of an object, function or enumerator does  not  hide
  the  name of a class or enumeration declared in a different namespace.
  For example,
          namespace A { class X { }; }
          namespace B { void X(int); }
          using namespace A;
          using namespace B;
          void f() {
                  X(1);        // error: name X found in two namespaces
          }
   --end note]

6 During overload resolution, all functions from the  transitive  search
  are  considered  for argument matching.  The set of declarations found
  by the transitive search is  unordered.   [Note:  in  particular,  the
  order  in which namespaces were considered and the relationships among
  the namespaces implied by the using-directives do not cause preference
  to  be  given  to  any  of the declarations found by the search.  ] An
  ambiguity exists if the best match finds two functions with  the  same
  signature,  even  if  one  is  in a namespace reachable through using-
  directives in the namespace of the other.5) [Example:
          namespace D {
                  int d1;
                  void f(char);
          }
          using namespace D;

          int d1;            // ok: no conflict with D::d1
          namespace E {
                  int e;
                  void f(int);
          }
          namespace D {       // namespace extension
                  int d2;
                  using namespace E;
                  void f(int);
          }
          void f()
          {
                  d1++;      // error: ambiguous ::d1 or D::d1?
                  ::d1++;    // ok
                  D::d1++;   // ok
                  d2++;      // ok: D::d2
                  e++;       // ok: E::e
                  f(1);      // error: ambiguous: D::f(int) or E::f(int)?
                  f('a');    // ok: D::f(char)
          }
   --end example]

  7.4  The asm declaration                                     [dcl.asm]

1 An asm declaration has the form
          asm-definition:
                  asm ( string-literal ) ;
  The meaning of an asm declaration is  implementation-defined.   [Note:
  Typically it is used to pass information through the implementation to
  an assembler.  ]

  _________________________
  5) During name lookup in a class hierarchy, some  ambiguities  may  be
  resolved  by considering whether one member hides the other along some
  paths (_class.member.lookup_).  There is no such  disambiguation  when
  considering  the  set  of  names found as a result of following using-
  directives.

  7.5  Linkage specifications                                 [dcl.link]

1 Linkage (_basic.link_) between C++ and  non-C++ code fragments can  be
  achieved using a linkage-specification:
          linkage-specification:
                  extern string-literal { declaration-seqopt }
                  extern string-literal declaration
  The string-literal indicates the required linkage.  The meaning of the
  string-literal is implementation-defined.  Every implementation  shall
  provide  for  linkage  to  functions written in the C programming lan­
  guage, "C", and linkage to C++ functions, "C++".  Default  linkage  is
  "C++".  [Example:
          complex sqrt(complex);    // C++ linkage by default
          extern "C" {
              double sqrt(double);  // C linkage
          }
   --end example]

  +-------                      BEGIN BOX 1                     -------+
  This  example  might  need to be revisited depending on what the rules
  ultimately are concerning C++ linkage to  standard  library  functions
  from the C library.
  +-------                       END BOX 1                      -------+

2 Linkage  specifications  nest.   When  linkage  spefications nest, the
  innermost one determines the linkage.  A  linkage  specification  does
  not  establish  a  scope.   A  linkage-specification can occur only in
  namespace scope (_basic.scope_).  A linkage-specification for a  class
  applies  to  nonmember  functions  and  objects declared within it.  A
  linkage-specification for a function also  applies  to  functions  and
  objects  declared within it.  A linkage declaration with a string that
  is unknown to the implementation is ill-formed.

3 If two declarations of the same function or object  specify  different
  linkage-specifications  (that  is, the linkage-specifications of these
  declarations specify different string-literals), the program  is  ill-
  formed  if  the  declarations appear in the same translation unit, and
  the one definition rule (_basic.def.odr_) applies if the  declarations
  appear  in different translation units.  Except for functions with C++
  linkage, a function declaration without a linkage specification  shall
  not  precede  the  first  linkage  specification for that function.  A
  function can be declared without  a  linkage  specification  after  an
  explicit  linkage  specification has been seen; the linkage explicitly
  specified in the earlier declaration is not affected by such  a  func­
  tion declaration.

4 At  most one of a set of overloaded functions (_over_) with a particu­
  lar name can have C linkage.

5 Linkage can be specified for objects.  [Example:

          extern "C" {
              // ...
              _iobuf _iob[_NFILE];
              // ...
              int _flsbuf(unsigned,_iobuf*);
              // ...
          }
   --end example] Functions and objects can be declared static or inline
  within  the  {}  of a linkage specification.  The linkage directive is
  ignored for a function or object with internal linkage (_basic.link_).
  A  function  first  declared  in  a linkage specification behaves as a
  function with external linkage.  [Example:
          extern "C" double f();
          static double f();     // error
  is ill-formed (_dcl.stc_).  ] An object defined within an
          extern "C" { /* ... */ }
  construct is still defined (and not just declared).

6 The linkage of a pointer to function affects only the  pointer.   When
  the  pointer  is dereferenced, the function to which it refers is con­
  sidered to be a C++ function.  There is no way  to  specify  that  the
  function to which a function pointer refers is written in another lan­
  guage.

  +-------                      BEGIN BOX 2                     -------+
  This is not a wholly satisfactory state of affairs
  +-------                       END BOX 2                      -------+

7 Linkage from C++ to objects defined in other languages and to  objects
  defined in C++ from other languages is implementation-defined and lan­
  guage-dependent.  Only where the object layout strategies of two  lan­
  guage implementations are similar enough can such linkage be achieved.
  Taking the address of a function whose linkage is other than C++ or  C
  produces undefined behavior.

8 When  the  name  of  a programming language is used to name a style of
  linkage in the string-literal in a linkage-specification, it is recom­
  mended that the spelling be taken from the document defining that lan­
  guage, [Example: Ada (not ADA) and Fortran or  FORTRAN  (depending  on
  the vintage).  ]